#sql #postgresql
#sql #postgresql
Вопрос:
У меня есть таблица, подобная
group | date
a | 2002-01-03
a | 2002-01-17
a | 2002-03-18
b | 2001-01-02
Я бы хотел превратить это в серию интервалов, таких как
group | start | stop
a | 2002-01-03 | 2002-01-17
a | 2002-01-17 | 2002-03-18
a | 2002-03-18 |
b | 2001-01-02 |
Я мог бы сделать это с
select distinct on (left.group, left.date)
left.group as group,
left.date as start,
right.date as stop
from dates as left
left join dates as right
on left.group = right.group
and left.date < right.date
order by group, left.date, right.date
но есть ли лучший способ сделать это (большое объединение и сортировка в реальной таблице выполняются медленно)
Ответ №1:
Используйте lead()
:
select d.*, lead(d.date) over (partition by d.group order by date)
from dates d
order by group, start;
Комментарии:
1. должно ли это быть «выбрать d.*, перейти (d.date) поверх (разделение по d.групповому порядку по дате) из дат, упорядоченных по d.date», или этот внешний «порядок по» не нужен?
2. @fgregg Внешний «порядок по» не нужен, поскольку он обрабатывается в
OVER()
предложении. Оконные функции запускаются после реализации набора данных.3. @fgregg . , , Если вы хотите получить результаты в определенном порядке, то вы всегда должны включать an
order by
в самый внешний запрос. Игнорируйте то, что прокомментировал JSpratt. Это просто неправильно.