SQL-запрос с группировкой по - PullRequest
1 голос
/ 23 февраля 2012

Я использую postgresql и задаюсь вопросом, могу ли я сделать это одним запросом: У меня есть таблица с четырьмя столбцами: идентификатор, начало, конец и user_id В одном запросе я делаю

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

Теперь было бы замечательно, если бы я где-то сохранил идентификаторы извлеченных строк, потому что они мне понадобятся позже в коде Это вообще возможно? Большое спасибо

Ответы [ 3 ]

3 голосов
/ 23 февраля 2012

Вы должны взглянуть на Функции и разделы окна или, возможно, 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 будетreturn:

10  | 1
20  | 2

Я предполагаю, что вам не нужен вывод этого запроса (поскольку вы также можете не использовать агрегаты, если вы используете столбец с уникальным ненулевым ограничением в вашем GROUP BY, как я предполагаю id is): 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, чтобы объединить все идентификаторы в массив:

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
1 голос
/ 24 февраля 2012

Если вам нужна строка как результат (не массив), вы можете упростить задачу с помощью 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
0 голосов
/ 23 февраля 2012

Предполагая, что id это идентификатор строки, вы пробовали это?

SELECT id, sum(finish - start) as duration, user_id group by id, user_id
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...