2012-02-23 173 views
1

我使用PostgreSQL和想知道如果我能做到这一点的一个请求: 我有四列的表:ID,开始,结束和user_id说明 在一个要求,我做了SQL查询通过

SELECT sum(finish - start) as duration, user_id group by user_id

现在,如果我保存某些地方的获取行的ID太多了,因为我在代码中需要它们以后 这可能吗? 非常感谢

回答

0

假设id是行ID,你试过吗?

SELECT id, sum(finish - start) as duration, user_id group by id, user_id
3

你应该看看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 
+0

非常感谢布鲁诺,这正是我一直在寻找的! – 2012-02-23 11:52:42

+0

@PomponVdp:这似乎是解决您的问题的方法。所以你会投票答复(如果你还没有),并接受答案作为你的问题的最佳解决方案。要做到这一点,请点击投票柜台下的V。 – tscho 2012-02-23 21:21:08

1

如果你想要一个字符串作为结果(不是数组),那么你就可以在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