sqlite 如何计算运行SUM?

q35jwt9p  于 2022-11-24  发布在  SQLite
关注(0)|答案(6)|浏览(178)

如何获得一列,该列是另一列前面值的总和?

0ve6wy6x

0ve6wy6x1#

自2018年9月15日起,SQLite 3.25.0支持window functions及其关键字OVER。现在,您的问题的答案很简单:

SELECT Country, Gdp, SUM(Gdp) OVER (ROWS UNBOUNDED PRECEDING)
FROM CountryGdp;

这是一个完成请求的最小查询,但它没有定义任何排序,因此这里有一个更合适的方法。

SELECT
    Country,
    Gdp,
    SUM(Gdp) OVER (
        ORDER BY Country -- Window ordering (not necessarily the same as result ordering!)
        ROWS BETWEEN -- Window for the SUM includes these rows:
            UNBOUNDED PRECEDING -- all rows before current one in window ordering
            AND CURRENT ROW -- up to and including current row.
        ) AS RunningTotal
FROM CountryGdp
ORDER BY Country;

时间复杂度为O(N)。

9rnv2umw

9rnv2umw2#

您可以通过将表与其自身联接(执行所谓的笛卡尔联接或交叉联接)来实现此目的。请参阅以下示例。

SELECT a.name, a.gdppc, SUM(b.gdppc)
FROM gdppc AS a, gdppc AS b WHERE b.gdppc <= a.gdppc 
GROUP BY b.id ORDER BY a.gdppc;

给定一个包含国家及其人均GDP的表格,它会给你一个GDP数字的运行总数。

Democratic Republic of Congo|329.645|329.645
Zimbabwe|370.465|700.11
Liberia|385.417|1085.527
Burundi|399.657|1485.184
Eritrea|678.954|2164.138
Niger|711.877|2876.015
Central African Republic|743.945|3619.96
Sierra Leone|781.594|4401.554
Togo|833.803|5235.357
Malawi|867.063|6102.42
Mozambique|932.511|7034.931
...

注意,这可能是一个非常耗费资源的操作,因为如果一个表有N个元素,它将创建一个有N*N个元素的临时表。

mum43rcc

mum43rcc3#

.(N^2)时间复杂度:O(N^2)时间复杂度:O(N^2)时间复杂度:.(N^2)时间复杂度:.(N^2)
这会产生与他相同的输出。

WITH RECURSIVE running(id, name, gdppc, rt) AS (
    SELECT row1._rowid_, row1.name, row1.gdppc, COALESCE(row1.gdppc,0)
    FROM gdppc AS row1
    WHERE row1._rowid_ = (
        SELECT a._rowid_
        FROM gdppc AS a
        ORDER BY a.gdppc, a.name, a._rowid_
        LIMIT 1)
    UNION ALL
    SELECT row_n._rowid_, row_n.name, row_n.gdppc, COALESCE(row_n.gdppc,0)+running.rt
    FROM gdppc AS row_n INNER JOIN running
    ON row_n._rowid_ = (
        SELECT a._rowid_
        FROM gdppc AS a
        WHERE (a.gdppc, a.name, a._rowid_) > (running.gdppc, running.name, running.id)
        ORDER BY a.gdppc, a.name, a._rowid_
        LIMIT 1))
SELECT running.name, running.gdppc, running.rt
FROM running;

排序和比较处理重复项,COALESCE用于忽略NULL。
如果你有一个很好的索引,那么这应该是O(N log N)。因为SQLite不支持游标,所以如果不依赖于外部应用程序,O(N)的解决方案可能不存在。

o8x7eapl

o8x7eapl4#

如果你有一个不支持OVER的SQLite版本,这里有另一种方法,对行的group_concat字符串使用递归。
在SQLite version 3.22.0 2018-01-22 18:45:57 group_concat上,按数据库顺序返回行。创建一个公共表表达式,并按不同顺序对其排序,如示例中的表work 1。

/* cumulative running total using group_concat and recursion
   adapted from https://blog.expensify.com/2015/09/25/the-simplest-sqlite-common-table-expression-tutorial/
*/

WITH RECURSIVE work2 AS (
  SELECT NULL AS name, NULL AS gdppc, 0 AS cum, (select group_concat(name) from work1) AS gcname, (select group_concat(gdppc) from work1) AS gcgdppc 
  UNION
        SELECT
            CASE
                WHEN INSTR(gcname, ',' )>0 THEN 
                    SUBSTR(gcname, 0, INSTR(gcname,','))
                ELSE
                    gcname
            END,
            CASE
                WHEN INSTR(gcgdppc, ',' )>0 THEN 
                    SUBSTR(gcgdppc, 0, INSTR(gcgdppc,','))
                ELSE
                    gcgdppc
            END,
            CASE
                WHEN INSTR(gcgdppc, ',' )>0 THEN 
                    cum + SUBSTR(gcgdppc, 0, INSTR(gcgdppc,','))
                ELSE
                    cum + gcgdppc
            END,
            CASE
                WHEN INSTR( gcname, ',' )>0 THEN 
                    SUBSTR( gcname, INSTR( gcname, ',' )+1 )
                ELSE
                    NULL
            END,
            CASE
                WHEN INSTR(gcgdppc, ',' )>0 THEN 
                    SUBSTR( gcgdppc, INSTR( gcgdppc, ',' )+1 )
                ELSE
                    NULL
            END
        FROM work2
        WHERE gcgdppc IS NOT NULL

  ), 
/* SQLite version 3.22.0 2018-01-22 18:45:57
   group_concat ignores ORDER BY when specified against the base table
   but does appear to follow the order of a common table expression 
*/
  work1 AS (select * from gdppc order by gdppc),

  gdppc AS (SELECT 'Burundi' AS name,399.657 AS gdppc
            UNION
            SELECT 'Democratic Republic of Congo', 329.645
            UNION
            SELECT 'Liberia',385.417
            UNION
            SELECT 'Zimbabwe',370.465)

select name,gdppc,cum from work2 where name IS NOT NULL;
/* result
Democratic Republic of Congo|329.645|329.645
Zimbabwe|370.465|700.11
Liberia|385.417|1085.527
Burundi|399.657|1485.184
*/
ghhkc1vu

ghhkc1vu5#

由于这篇文章是谷歌搜索“sqlite滚动求和”的最佳结果,我将添加下面的答案。
top answer by relatively_random非常适合累计求和。但是,如果您想将其调整为滚动求和(可能是7天滚动求和),可以通过添加CASE表达式来检查窗口是否具有所需的大小(例如7)。1
这是必要的(?),因为通常情况下,如果滚动窗口的大小小于预期大小,滚动计算将返回NULL。例如,如果我们正在计算7天的滚动总和,则前6行的总计应为NULL,因为还不到7天。

SELECT
    date,
    price,
    CASE
        WHEN COUNT(*) OVER win >= 7 THEN SUM(price) OVER win
    END AS seven_day_rolling_total
FROM price_data
WINDOW win AS (
    ORDER BY date
    ROWS 6 PRECEDING
)
--LIMIT 10;

1:为了使查询更容易阅读,我在SELECT语句之后定义了窗口,因为它被使用了两次。

hgqdbh6s

hgqdbh6s6#

您必须在所需字段中进行求和....查询取决于您使用的数据库,Oracle允许您执行以下操作:

select id, value, sum(value) as partial_sum over (order by id) from table

相关问题