1

У меня есть данные, как это:Как сгруппировать следующие строки, не уникальное значение

table1 
_____________ 
id way time 
1 1 00:01 
2 1 00:02 
3 2 00:03 
4 2 00:04 
5 2 00:05 
6 3 00:06 
7 3 00:07 
8 1 00:08 
9 1 00:09 

Я хотел бы знать, в какой промежуток времени я был на какой путь:

desired output 
_________________ 
id way from to  
1 1 00:01 00:02 
3 2 00:03 00:05 
6 3 00:06 00:07 
8 1 00:08 00:09 

Я пытался использовать функцию окна:

SELECT DISTINCT 
    first_value(id) OVER w AS id, 
    first_value(way) OVER w as way, 
    first_value(time) OVER w as from, 
    last_value(time) OVER w as to 
FROM table1 
WINDOW w AS (
    PARTITION BY way ORDER BY ID 
    range between unbounded preceding and unbounded following); 

Что я получаю:

ID way from to  
1 1 00:01 00:09 
3 2 00:03 00:05 
6 3 00:06 00:07 

И это не правильно, потому что на пути 1 меня не было с 00:01 до 00:09. Есть ли возможность сделать раздел в соответствии с порядком, означает группировку только следующих атрибутов, которые равны?

+1

Как «путь» '' '00:03 - 00: 05' и' путь'' 3'' 00: 06-00: 07'? Это очень запутанно. – JNevill

+0

Это было неправильно, я исправил это. Спасибо. – telemachos

+0

Вы делаете это похоже на 'id' и' time', оба будут строго восходящим параллельно. Это так? Ты уверен? Если 'id' является столбцом' serial', это, скорее всего, ***, а не *** всегда случай. Это означало бы, что минимальный 'id' и минимальный' time' для одного временного фрагмента может быть в разных строках. Что должно быть в результате? –

ответ

2

Если ваш случай так же просто, как пример значение предполагает, @Giorgos' answer служит хорошо.

Однако, это обычно не в случае. Если столбец 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 оконная рамка охватывает все строки PARTITION, поэтому мы получаем абсолютный максимум за срез времени.

  • Наружный слой запроса необходим только для получения желаемого порядка сортировки в результате, поскольку мы обязаны в подзапросах sub другого ORDER BY с помощью DISTINCT ON. Реквизиты:

SQL Fiddle демонстрирует случай использования.

Если вы хотите оптимизировать производительность, функция plpgsql может быть быстрее в таком случае. Тесно связанные с ответом:

Кроме: не использовать основное имя типа time в качестве идентификатора (также reserved word in standard SQL).

2

Я думаю, что вы хотите что-то вроде этого:

select min(id), way, 
     min(time), max(time) 
from (
select id, way, time, 
     ROW_NUMBER() OVER (ORDER BY id) - 
     ROW_NUMBER() OVER (PARTITION BY way ORDER BY time) AS grp 
from table1) t 
group by way, grp 

grp отождествляет 'островов' последовательныхway значений. Используя это вычисленное поле во внешнем запросе, мы можем получить начало и конец раз way интервалов с использованием MIN и MAX совокупных функций соответственно.

Demo here

+0

@ Нассим OP хочет идентифицировать острова * последовательных значений '' way'. В данных выборочных данных имеется ** 4 ** из них. Пожалуйста, посмотрите * желаемый результат * и * не * на *, что я получаю * вывод. –

+0

Да, я неправильно понял вопрос, поэтому я удалил свой ответ, в этом случае ваш ответ более точным +1 – Nassim