Pab*_*pia 7 postgresql group-by sum rows 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";
Run Code Online (Sandbox Code Playgroud)
我需要做的是获得每行的计数总和以及过去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
Run Code Online (Sandbox Code Playgroud)
Mil*_*los 12
这是对当前行和前N行(在您的情况下N = 2)的值之和的更通用的解决方案.
SELECT "date",
sum("count") OVER (order by "date" ROWS BETWEEN 2 preceding AND current row)
FROM t
ORDER BY "date";
Run Code Online (Sandbox Code Playgroud)
您可以在0和"Unbounded"之间更改N. 这种方法让您有机会在您的应用中拥有一个参数"N过去几分钟的计数".此外,如果超出范围,则无需处理默认值.
您可以在PostgreSQL文档中找到更多相关信息(4.2.8.窗口函数调用)
vye*_*rov 11
这对于lag()
窗口函数来说并不是那么棘手(同样在SQL Fiddle上):
CREATE TABLE t ("date" timestamptz, "count" int4);
INSERT INTO t 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 *,
"count"
+ coalesce(lag("count", 1) OVER (ORDER BY "date"), 0)
+ coalesce(lag("count", 2) OVER (ORDER BY "date"), 0) AS "total"
FROM t;
Run Code Online (Sandbox Code Playgroud)
date
和count
列,因为这些是保留字;lag(field, distance)
给出了我离开当前行的field
列distance
行的值,因此第一个函数给出了前一行的值,第二个调用给出了前一行的值;coalesce()
需要避免函数的NULL
结果lag()
(对于查询的第一行,没有"前一个",因此它是NULL
),否则total
也将是NULL
.@ vyegorov的答案主要涵盖了它.但是我有更多的抱怨而不适合评论.
不要使用保留字状date
,并count
作为标识符在所有.PostgreSQL允许这两个特定的关键词作为标识符 - 除了每个SQL标准.但这仍然是不好的做法.事实上你可以使用双引号内的任何东西作为标识符,甚至"; DELETE FROM tbl;"
不是一个好主意.这个名字"date"
的timestamp
是最重要的是误导性的.
数据类型错误.示例显示timestamp
,而不是timestamptz
.这里没有什么不同,但仍然具有误导性.
你不需要COALESCE()
.使用窗口函数lag()
,lead()
您可以提供默认值作为第3个参数:
在此设置的基础上:
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);
Run Code Online (Sandbox Code Playgroud)
查询:
SELECT ts, ct + lag(ct, 1, 0) OVER (ORDER BY ts)
+ lag(ct, 2, 0) OVER (ORDER BY ts) AS total
FROM tbl;
Run Code Online (Sandbox Code Playgroud)
或者更好的是:使用单个sum()
窗口聚合函数和自定义窗口框架:
SELECT ts, sum(ct) OVER (ORDER BY ts ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)
FROM tbl;
Run Code Online (Sandbox Code Playgroud)
结果相同.
有关:
归档时间: |
|
查看次数: |
5343 次 |
最近记录: |