インターリーブする行間の同じ列の日付の範囲の違いをどのように最もよく合計しますか日時列があり、行間の差を計算したいと思います。秒の差が欲しい。この質問は、2つのタイムスタンプの違いを取得する方法ではなく、同じテーブルの行間で最も効率的に計算する方法に重点を置いています。私の場合、各行には、2つの行を論理的にリンクする日時の偶数型があります。
開始と終了のイベントタイプをグループ化する方法に関する詳細。 (Andriy Mの質問)開始と終了は連続しているはずです。開始に後続の終了がない場合は、合計から除外する必要があります。次の開始に移動して、終了があるかどうかを確認します。合計秒数の合計には、連続する開始-終了ペアのみを追加する必要があります。
Postgresql 9.xでの作業...
表のデータの例。
eventtype, eventdate
START, 2015-01-01 14:00
END, 2015-01-01 14:25
START, 2015-01-01 14:30
END, 2015-01-01 14:43
START, 2015-01-01 14:45
END, 2015-01-01 14:49
START, 2015-01-01 14:52
END, 2015-01-01 14:55
すべての開始日と終了日は連続していることに注意してください。
これが私の最初の試みです。動作しているようです。
SELECT
-- starts.*
SUM(EXTRACT(Epoch FROM (eventdate_next - eventdate))) AS duration_seconds
FROM
(
WITH x AS (
SELECT *, dense_rank() OVER (ORDER BY eventdate) AS rnk
FROM table
AND eventdate > '2015-01-01 00:00:00.00'
AND eventdate < '2016-01-01 23:59:59.59'
)
SELECT x.eventdate, x.eventtype, y.eventdate AS eventdate_next, y.eventtype AS eventtype_next
FROM x
LEFT JOIN (SELECT DISTINCT eventdate, eventtype, rnk FROM x) y ON y.rnk = (x.rnk + 1)
ORDER BY x.eventdate
) starts
WHERE
eventtype = 'START'
GROUP BY eventtype
私の最初の試みは、stackoverflowのすばらしい例に基づいています Postgres 9.1-次の値の取得
注意; GROUP BYとSUMにコメントを付け、starts。*のコメントを外して、合計に入る個々の期間のレコードを取得できます。
LEAD
分析関数を使用して、現在の行のデータとともに次の行のeventtype
およびeventdate
を取得できます。
SELECT
eventtype,
eventdate,
LEAD(eventtype) OVER (ORDER BY eventdate) AS nexttype,
LEAD(eventdate) OVER (ORDER BY eventdate) AS nextdate
FROM
atable
WHERE
eventdate >= '2015-01-01 00:00:00.00'
AND eventdate < '2016-01-01 23:59:59.59'
上記のクエリを派生テーブルとして使用すると、eventtype = 'START' AND nexttype = 'END'
で出力をさらにフィルタリングして、差の合計を取得できます。
SELECT
SUM(EXTRACT(Epoch FROM (nextdate - eventdate))) AS duration_seconds
FROM
(
SELECT
eventtype,
eventdate,
LEAD(eventtype) OVER (ORDER BY eventdate) AS nexttype,
LEAD(eventdate) OVER (ORDER BY eventdate) AS nextdate
FROM
atable
WHERE
eventdate >= '2015-01-01 00:00:00.00'
AND eventdate < '2016-01-01 23:59:59.59'
) AS s
WHERE
eventtype = 'START'
AND nexttype = 'END'
;
わずかなバリエーションとして、サブクエリをCTEとして実装できます。
WITH cte AS
(
SELECT
eventtype,
eventdate,
LEAD(eventtype) OVER (ORDER BY eventdate) AS nexttype,
LEAD(eventdate) OVER (ORDER BY eventdate) AS nextdate
FROM
atable
WHERE
eventdate >= '2015-01-01 00:00:00.00'
AND eventdate < '2016-01-01 23:59:59.59'
)
SELECT
SUM(EXTRACT(Epoch FROM (nextdate - eventdate))) AS duration_seconds
FROM
cte
WHERE
eventtype = 'START'
AND nexttype = 'END'
;
派生テーブルとは異なり、CTEはPostgreSQLで実現されるため、この書き換えはパフォーマンスに影響を与える可能性があります。テストにより、違いがあるかどうか、ある場合はどちらのオプションが適しているかが明らかになります。