Как разбить столбцы времени начала / окончания на отдельные порции с PostgreSQL? - PullRequest
4 голосов
/ 24 сентября 2010

У нас есть несколько таблиц, которые имеют такую ​​структуру:

начало, - дата и время
конец, - дата / время
стоимость - десятичная

Так, например, может быть строка вроде:

01.01.2010 10:08, 01.01.2010 13:56, 135.00
01.01.2010 11:01, 01.01.2010 15:22, 118.00
01.01.2010 06:19, 01.02.2010 1:43, 167.00

Etc ...

Я бы хотел получить это в формате (с функцией?), Который возвращает данные в формате, подобном:

10:00, 10:15, X, Y, Z
10:15, 10:30, X, Y, Z
10:30, 10:45, X, Y, Z
10:45, 11:00, X, Y, Z
11:00, 11:15, X, Y, Z

....

Где:
X = количество строк, соответствующих
Y = стоимость / затраты за этот отрезок времени
Z = общее количество времени в течение этой продолжительности

IE, для приведенных выше данных у нас может быть:

10: 00, 10:15, 1 (135/228 минут * 7), 7

  • Первый ряд начинается в 10:08, поэтому с 10:00 до 10:15 используется только 7 минут.
  • Время начала и окончания составляет 228 минут.

....

11:00, 11:15, 2, ((135 + 118) / ((228 + 261) минут * (15 + 14)), 29

  • Второй ряд начинается сразу после 11:00, поэтому нам нужно 15 минут от первого ряда, плюс 14 минут от второго ряда
  • Во втором пуске -> время окончания 261 минута

....

Полагаю, что здесь я сделал математику, но мне нужно выяснить, как превратить это в функцию PG, чтобы ее можно было использовать в отчете.

В идеале я хотел бы иметь возможность вызывать функцию с произвольной длительностью, то есть 15 минут, или 30 минут, или 60 минут, и разделить ее на основании этого.

Есть идеи?

1 Ответ

5 голосов
/ 24 сентября 2010

Вот моя попытка.Учитывая это определение таблицы:

CREATE TABLE interval_test
(
  "start" timestamp without time zone,
  "end" timestamp without time zone,
  "cost" integer
)

Этот запрос, кажется, делает то, что вы хотите.Не уверен, что это лучшее решение.Также обратите внимание, что для работы ему нужен Postgres 8.4, поскольку он использует функции WINDOW и запросы WITH.

WITH RECURSIVE intervals(period_start) AS (
    SELECT 
    date_trunc('hour', MIN(start)) AS period_start
      FROM interval_test

  UNION ALL
    SELECT intervals.period_start + INTERVAL '15 MINUTES'
      FROM  intervals
      WHERE (intervals.period_start + INTERVAL '15 MINUTES') < (SELECT MAX("end") FROM interval_test)
  )
  SELECT DISTINCT period_start, intervals.period_start + INTERVAL '15 MINUTES' AS period_end, 
  COUNT(*) OVER  (PARTITION BY period_start ) AS record_count,
SUM (LEAST(period_start + INTERVAL '15 MINUTES', "end")::timestamp - GREATEST(period_start, "start")::timestamp)
  OVER  (PARTITION BY period_start ) AS total_time,

  (SUM(cost) OVER  (PARTITION BY period_start ) /  


 (EXTRACT(EPOCH FROM SUM("end" - "start") OVER  (PARTITION BY period_start )) / 60)) * 

 ((EXTRACT (EPOCH FROM SUM (LEAST(period_start + INTERVAL '15 MINUTES', "end")::timestamp - GREATEST(period_start, "start")::timestamp)
  OVER  (PARTITION BY period_start )))/60)

   AS expense

FROM  interval_test
INNER JOIN intervals ON (intervals.period_start, intervals.period_start + INTERVAL '15 MINUTES') OVERLAPS (interval_test.start, interval_test.end)

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