2012-02-23 123 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