Я пытаюсь найти способ сравнения с текущей строкой в предложении PARTITION BY функции WINDOW в запросе PostgreSQL.
Представьте, что у меня есть короткий список в следующем запросе из этих 5 элементов (в реальном случае у меня есть тысячи или даже миллионы строк). Я пытаюсь получить для каждой строки идентификатор следующего другого элемента (столбца событий) и идентификатор предыдущего другого элемента.
WITH events AS(
SELECT 1 as id, 12 as event, '2014-03-19 08:00:00'::timestamp as date
UNION SELECT 2 as id, 12 as event, '2014-03-19 08:30:00'::timestamp as date
UNION SELECT 3 as id, 13 as event, '2014-03-19 09:00:00'::timestamp as date
UNION SELECT 4 as id, 13 as event, '2014-03-19 09:30:00'::timestamp as date
UNION SELECT 5 as id, 12 as event, '2014-03-19 10:00:00'::timestamp as date
)
SELECT lag(id) over w as previous_different, event
, lead(id) over w as next_different
FROM events ev
WINDOW w AS (PARTITION BY event!=ev.event ORDER BY date ASC);
Я знаю, что сравнение event!=ev.event
некорректно, но именно этого я и хочу достичь.
Результат, который я получаю (так же, как если бы я удалил предложение PARTITION BY):
|12|2
1|12|3
2|13|4
3|13|5
4|12|
И результат, который я хотел бы получить:
|12|3
|12|3
2|13|5
2|13|5
4|12|
Кто-нибудь знает, возможно ли это и как? Большое спасибо!
EDIT: я знаю, что могу сделать это с двумя JOIN
, ORDER BY
и DISTINCT ON
, но в реальном случае с миллионами строк это очень неэффективно:
WITH events AS(
SELECT 1 as id, 12 as event, '2014-03-19 08:00:00'::timestamp as date
UNION SELECT 2 as id, 12 as event, '2014-03-19 08:30:00'::timestamp as date
UNION SELECT 3 as id, 13 as event, '2014-03-19 09:00:00'::timestamp as date
UNION SELECT 4 as id, 13 as event, '2014-03-19 09:30:00'::timestamp as date
UNION SELECT 5 as id, 12 as event, '2014-03-19 10:00:00'::timestamp as date
)
SELECT DISTINCT ON (e.id, e.date) e1.id, e.event, e2.id
FROM events e
LEFT JOIN events e1 ON (e1.date<=e.date AND e1.id!=e.id AND e1.event!=e.event)
LEFT JOIN events e2 ON (e2.date>=e.date AND e2.id!=e.id AND e2.event!=e.event)
ORDER BY e.date ASC, e.id ASC, e1.date DESC, e1.id DESC, e2.date ASC, e2.id ASC
SELECT ... UNION
для генерации тестовых данных вы можете использовать гораздо более короткое предложениеvalues
: sqlfiddle .com/#!15/d41d8/1471 - person a_horse_with_no_name   schedule 19.03.2014date
) уникальной? - person Erwin Brandstetter   schedule 20.03.2014RANGE
, которое PostgreSQL пока не поддерживает. Я боюсь, что вы можете застрять с объединениями, поскольку диапазоны до и после потенциально не ограничены. - person Craig Ringer   schedule 20.03.2014id
кORDER BY
и др. Не забудьте предоставить всю необходимую информацию в следующий раз, чтобы мы не теряли время зря. - person Erwin Brandstetter   schedule 20.03.2014