PostgreSQL - Создай секунду за другим View - PullRequest
0 голосов
/ 07 сентября 2018

У меня есть таблица с именем tb_records, которая является записью событий. Примеры значений:

id  from        to
1   01:00:00    01:00:03
2   01:00:05    01:00:07
3   01:00:50    01:00:51

То, что я хотел бы сделать, это сгенерировать последовательность за секундой в PostgreSQL. Таким образом, результат будет

id  from        to          time
1   01:00:00    01:00:03    01:00:00
1   01:00:00    01:00:03    01:00:01
1   01:00:00    01:00:03    01:00:02
1   01:00:00    01:00:03    01:00:03
2   01:00:05    01:00:07    01:00:05
2   01:00:05    01:00:07    01:00:06
2   01:00:05    01:00:07    01:00:07
3   01:00:50    01:00:51    01:00:50
3   01:00:50    01:00:51    01:00:51

Обычно, в Python или R, алгоритм basic , который я бы выбрал (без использования какой-либо библиотеки или пакета):

  1. Рассчитать разницу времени в секундах для каждого id (diff)
  2. Для каждого идентификатора реплицируйте строки на diff
  3. Создать столбец time с начальными значениями в виде столбца from
  4. Для каждой id и строки столбец приращения time на одну секунду

Я не совсем понимаю, как это сделать в SQL, поскольку я привык создавать эти шаги последовательно.

Ответы [ 2 ]

0 голосов
/ 07 сентября 2018

Используйте таблицу календаря и присоединитесь к ней. (Я переименовал столбцы; «to», «from» и «time» - все зарезервированные слова в SQL)


WITH omg AS ( -- calendar table
        SELECT generate_series( min(tfrom),max(tto),'1sec'::interval) AS ttick
                 FROM fromto t
        )
SELECT t.id, t.tfrom, t.tto
        , o.ttick
FROM fromto t
JOIN omg o -- join it with actual table
        ON t.tfrom <= o.ttick
        AND t.tto >= o.ttick
ORDER BY o.ttick
        ;

Или используйте рекурсивный CTE:


WITH RECURSIVE wtf AS (
        SELECT t.id, t.tfrom, t.tto
                , t.tfrom AS ttick      -- pick the lower bound
        FROM fromto t
        UNION ALL
        SELECT w.id, w.tfrom, w.tto
                , (w.ttick+ '1sec'::interval) AS ttick -- add one second
        FROM wtf w
        WHERE w.ttick < w.tto           -- if below the upper bound
        )
SELECT * FROM wtf
        ;
0 голосов
/ 07 сентября 2018
select id, "from", "to",
generate_series(('2000-01-01 '||"from")::timestamp, ('2000-01-01 '||"to")::timestamp, '1 second'::interval)::time as res
from tb_records
order by id, res 

generate_series() не работает с типом time, поэтому я конвертирую time в timestamp, а затем извлекаю time часть из сгенерированного результата.

SQL Fiddle Demo

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...