Postgresql 表中每3行求和一次
我有以下查询来计算每分钟的所有数据Postgresql 表中每3行求和一次,postgresql,sum,rows,group-by,window-functions,Postgresql,Sum,Rows,Group By,Window Functions,我有以下查询来计算每分钟的所有数据 $sql= "SELECT COUNT(*) AS count, date_trunc('minute', date) AS momento FROM p WHERE fk_id_b=$id_b GROUP BY date_trunc('minute', date) ORDER BY momento ASC"; 我需要做的是得到每行的计数和过去2分钟的计数之和 For example with the result of the $sql query ab
$sql= "SELECT COUNT(*) AS count, date_trunc('minute', date) AS momento
FROM p WHERE fk_id_b=$id_b GROUP BY date_trunc('minute', date)
ORDER BY momento ASC";
我需要做的是得到每行的计数和过去2分钟的计数之和
For example with the result of the $sql query above
|-------date---------|----count----|
|2012-06-21 05:20:00 | 12 |
|2012-06-21 05:21:00 | 14 |
|2012-06-21 05:22:00 | 10 |
|2012-06-21 05:23:00 | 20 |
|2012-06-21 05:24:00 | 25 |
|2012-06-21 05:25:00 | 30 |
|2012-06-21 05:26:00 | 10 |
I want this result:
|-------date---------|----count----|
|2012-06-21 05:20:00 | 12 |
|2012-06-21 05:21:00 | 26 | 12+14
|2012-06-21 05:22:00 | 36 | 12+14+10
|2012-06-21 05:23:00 | 44 | 14+10+20
|2012-06-21 05:24:00 | 55 | 10+20+25
|2012-06-21 05:25:00 | 75 | 20+25+30
|2012-06-21 05:26:00 | 65 | 25+30+10
这一点在以下情况下不太棘手:
创建表t(“日期”timestamptz,“计数”int4);
插入到t值中
('2012-06-21 05:20:00',12),
('2012-06-21 05:21:00',14),
('2012-06-21 05:22:00',10),
('2012-06-21 05:23:00',20),
('2012-06-21 05:24:00',25),
('2012-06-21 05:25:00',30),
('2012-06-21 05:26:00',10);
选择*,
“计数”
+合并(滞后(“计数”,1)超过(按“日期”排序),0)
+合并(滞后(“计数”,2)超过(按“日期”排序),0)为“总计”
从t;
date
和count
列,因为它们是保留字李>
lag(field,distance)
给出了field
列distance
行与当前行之间的值,因此第一个函数给出了前一行的值,第二个调用给出了前一行的值李>
coalesce()
需要避免NULL
来自lag()
函数的结果(对于查询中的第一行,没有“previous”一行,因此它是NULL
),否则总计也将是NULL
date
和count
作为标识符。PostgreSQL允许这两个特定的关键字作为标识符,而不是每个SQL标准。但这仍然是一种坏习惯。您可以使用双引号内的任何内容作为标识符,即使是“DELETE FROM tbl;”
,也不是一个好主意。除此之外,时间戳的名称“date”
还有误导性
timestamptz
。在这里没有区别,但仍然有误导性COALESCE()
。使用,您可以提供默认值作为第三个参数:CREATE TABLE tbl (ts timestamp, ct int4);
INSERT INTO tbl VALUES
('2012-06-21 05:20:00', 12)
, ('2012-06-21 05:21:00', 14)
, ('2012-06-21 05:22:00', 10)
, ('2012-06-21 05:23:00', 20)
, ('2012-06-21 05:24:00', 25)
, ('2012-06-21 05:25:00', 30)
, ('2012-06-21 05:26:00', 10);
查询:
SELECT ts, ct + lag(ct, 1, 0) OVER (ORDER BY ts)
+ lag(ct, 2, 0) OVER (ORDER BY ts) AS total
FROM tbl;
或更好但:使用单个
sum()
作为窗口聚合函数,并使用:
同样的结果。相关的:
您可以在PostgreSQL文档()中找到更多关于这方面的信息。SQL非常棘手。你的申请不能完成这项工作吗?无论如何,您都必须获取行,并且您可以在同一个循环中这样做。@Parth Bhatt:您批准的编辑显然是在问一个不同的问题。请不要批准这样的编辑。@interjay:对不起,我弄错了,我解释错了。太好了!我喜欢窗口函数的概念,但总是忘记使用它们。对正确的解决方案投赞成票:-)+1。我写了一个答案,因为注释是不够的。默认值为
lag
/lead
是个不错的选择!
SELECT ts, sum(ct) OVER (ORDER BY ts ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)
FROM tbl;
SELECT "date",
sum("count") OVER (order by "date" ROWS BETWEEN 2 preceding AND current row)
FROM t
ORDER BY "date";