Ако вашият случай е толкова прост, колкото показват примерните стойности, отговорът на @Giorgos служи добре.
Това обаче обикновено не е така . Ако id
колоната е serial
, не можете да разчитате на предположението, че ред с по-ранен time
също има по-малък id
.
Също така, time
стойности (или timestamp
както вероятно имате) могат лесно да бъдат дубликати, трябва да направите реда на сортиране недвусмислен.
Ако приемем, че и двете могат да се случат и искате id
от реда с най-ранния time
на отрязък от време (всъщност, най-малкият id
за най-ранния време , може да има връзки), тази заявка ще се справи правилно със ситуацията:
SELECT *
FROM (
SELECT DISTINCT ON (way, grp)
id, way, time AS time_from
, max(time) OVER (PARTITION BY way, grp) AS time_to
FROM (
SELECT *
, row_number() OVER (ORDER BY time, id) -- id as tie breaker
- row_number() OVER (PARTITION BY way ORDER BY time, id) AS grp
FROM table1
) t
ORDER BY way, grp, time, id
) sub
ORDER BY time_from, id;
-
ORDER BY time, id
да бъде еднозначно. Ако приемем, че времето е не уникален, добавете (предполага се уникален)id
за да избегнете произволни резултати - които могат да се променят между заявките по подъл начин. -
max(time) OVER (PARTITION BY way, grp)
:безORDER BY
, рамката на прозореца обхваща всички редове на ДЯЛА, така че получаваме абсолютния максимум за отрязък от време. -
Външният слой на заявката е необходим само за създаване на желания ред на сортиране в резултата, тъй като сме обвързани с различен
ORDER BY
в подзаявкатаsub
чрез използване наDISTINCT ON
. Подробности:
SQL Fiddle демонстриране на случая на употреба.
Ако искате да оптимизирате производителността, функцията plpgsql може да бъде по-бърза в такъв случай. Тясно свързан отговор:
Настрана:не използвайте основното име на тип time
като идентификатор (също запазена дума в стандартния SQL ).