我使用PostgreSQL和想知道如果我能做到这一点的一个请求: 我有四列的表:ID,开始,结束和user_id说明 在一个要求,我做了SQL查询通过
SELECT sum(finish - start) as duration, user_id group by user_id
现在,如果我保存某些地方的获取行的ID太多了,因为我在代码中需要它们以后 这可能吗? 非常感谢
我使用PostgreSQL和想知道如果我能做到这一点的一个请求: 我有四列的表:ID,开始,结束和user_id说明 在一个要求,我做了SQL查询通过
SELECT sum(finish - start) as duration, user_id group by user_id
现在,如果我保存某些地方的获取行的ID太多了,因为我在代码中需要它们以后 这可能吗? 非常感谢
假设id
是行ID,你试过吗?
SELECT id, sum(finish - start) as duration, user_id group by id, user_id
你应该看看Window Functions and Partitions或许array_agg
。
假设这个例子:
CREATE TABLE mytable (
id SERIAL PRIMARY KEY,
user_id INTEGER,
start INTEGER,
finish INTEGER
);
INSERT INTO mytable(id, user_id, start, finish) VALUES (1, 1, 5, 10); -- duration: 5
INSERT INTO mytable(id, user_id, start, finish) VALUES (2, 2, 10, 30); -- duration: 20
INSERT INTO mytable(id, user_id, start, finish) VALUES (3, 1, 15, 20); -- duration: 5
如你所知,SELECT SUM(finish - start), user_id FROM mytable GROUP BY user_id
将返回:
10 | 1
20 | 2
我相信你不想要的是这个查询的输出(因为你还不如如果您在GROUP BY
中使用具有唯一非空约束的列,则不使用聚合,因为我假定id
为):SELECT id, SUM(finish - start), user_id FROM mytable GROUP BY user_id, id
。
使用窗口函数,可以使用与当前行相关的其他行的数据。
下面的查询:
SELECT id, SUM(finish - start) OVER (PARTITION BY user_id) AS duration, user_id
FROM mytable ORDER BY user_id
产生这些结果:
1 | 10 | 1
3 | 10 | 1
2 | 20 | 2
现在会习惯
你每id
一排,但
SUM
适用于整个组行的窗口内框架(在这里,所有与当前行相同的
user_id
)。
就您的应用而言,您可能需要逐一读取行,并将id
的相关值存储在某处,直到user_id
发生更改。
或者,你可以使用array_agg
到所有的ID汇总到一个数组:
SELECT array_agg(id), SUM(finish - start) AS duration, user_id
FROM mytable GROUP BY user_id ORDER BY user_id, duration
{1, 3} | 10 | 1
{2} | 20 | 2
如果,例如,你想这在一个空间分隔的字符串,在此之上使用array_to_string
:
SELECT array_to_string(array_agg(id), ' '), SUM(finish - start) AS duration, user_id
FROM mytable GROUP BY user_id ORDER BY user_id, duration
如果你想要一个字符串作为结果(不是数组),那么你就可以在string_agg()
PostgreSQL的9.0简化任务或更高版本:
SELECT user_id
, sum(finish - start) AS duration
, string_agg(id, ', ') AS ids
FROM tbl
GROUP BY 1
ORDER BY 1
非常感谢布鲁诺,这正是我一直在寻找的! – 2012-02-23 11:52:42
@PomponVdp:这似乎是解决您的问题的方法。所以你会投票答复(如果你还没有),并接受答案作为你的问题的最佳解决方案。要做到这一点,请点击投票柜台下的V。 – tscho 2012-02-23 21:21:08