Teradata 中分区 window 的时差(以小时和秒为单位)(会话记录)
Time difference in hours and seconds over a partition window in Teradata (Sessionizing Records)
给出这样的 table:
cust_id time
123 2015-01-01 12:15:05
123 2015-01-01 12:17:06
123 2015-01-02 13:15:08
123 2015-01-02 15:15:10
456 2015-01-01 10:15:05
456 2015-01-01 12:15:07
456 2015-01-01 14:11:10
我想通过 cust_id
计算每个前面的记录(想想 lag
函数)之间的时间差。我想要的输出:
cust_id time diff_hours diff_seconds
123 2015-01-01 12:15:05 NULL NULL
123 2015-01-01 12:17:06 0.00 121
123 2015-01-02 13:15:08 1.04 89882
123 2015-01-02 15:15:10 0.08 7202
456 2015-01-01 10:15:05 NULL NULL
456 2015-01-01 12:15:07 0.08 7202
456 2015-01-01 14:11:10 0.08 6963
如何在 Teradata 中完成此操作?
我尝试过类似的东西:
SELECT
*
, (time - time) OVER (PARTITION BY cust_id ORDER BY time ROWS BETWEEN 1 PRECEDING AND CURRENT ROW)
FROM
table_01
然而,虽然 NULL
出现在预期的位置,但我一直收到所有其他结果的 0.0
。我也尝试过将 (time - time)
与 SUM
一起使用,我也尝试过使用 EXTRACT(SECOND FROM TIME)
和其他一些变体——例如,尝试放置 DAY(4) to SECOND
,但我不能似乎 syntax/ordering/conversion 非常正确,尤其是将 window 函数混入其中时。
Teradata 中没有LAG
,但您可以重写它:
SELECT
t.*
, (time)
- min(time)
OVER (PARTITION BY cust_id
ORDER BY time
ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) SECOND(4)
FROM
table_01 as t
当您尝试获取秒数时,您会遇到 "Interval Overflow" 错误,即超过 9999 秒。要么更改为 DAY(4) TO SECOND
,要么使用我几年前写的这个 SQL UDF,用于计算两个时间戳的秒数之差:
REPLACE FUNCTION TimeStamp_Diff_Seconds
(
ts1 TIMESTAMP(6)
,ts2 TIMESTAMP(6)
)
RETURNS DECIMAL(18,6)
LANGUAGE SQL
CONTAINS SQL
RETURNS NULL ON NULL INPUT
DETERMINISTIC
SQL SECURITY DEFINER
COLLATION INVOKER
INLINE TYPE 1
RETURN
(CAST((CAST(ts2 AS DATE)- CAST(ts1 AS DATE)) AS DECIMAL(18,6)) * 60*60*24)
+ ((EXTRACT( HOUR FROM ts2) - EXTRACT( HOUR FROM ts1)) * 60*60)
+ ((EXTRACT(MINUTE FROM ts2) - EXTRACT(MINUTE FROM ts1)) * 60)
+ (EXTRACT(SECOND FROM ts2) - EXTRACT(SECOND FROM ts1))
;
给出这样的 table:
cust_id time
123 2015-01-01 12:15:05
123 2015-01-01 12:17:06
123 2015-01-02 13:15:08
123 2015-01-02 15:15:10
456 2015-01-01 10:15:05
456 2015-01-01 12:15:07
456 2015-01-01 14:11:10
我想通过 cust_id
计算每个前面的记录(想想 lag
函数)之间的时间差。我想要的输出:
cust_id time diff_hours diff_seconds
123 2015-01-01 12:15:05 NULL NULL
123 2015-01-01 12:17:06 0.00 121
123 2015-01-02 13:15:08 1.04 89882
123 2015-01-02 15:15:10 0.08 7202
456 2015-01-01 10:15:05 NULL NULL
456 2015-01-01 12:15:07 0.08 7202
456 2015-01-01 14:11:10 0.08 6963
如何在 Teradata 中完成此操作?
我尝试过类似的东西:
SELECT
*
, (time - time) OVER (PARTITION BY cust_id ORDER BY time ROWS BETWEEN 1 PRECEDING AND CURRENT ROW)
FROM
table_01
然而,虽然 NULL
出现在预期的位置,但我一直收到所有其他结果的 0.0
。我也尝试过将 (time - time)
与 SUM
一起使用,我也尝试过使用 EXTRACT(SECOND FROM TIME)
和其他一些变体——例如,尝试放置 DAY(4) to SECOND
,但我不能似乎 syntax/ordering/conversion 非常正确,尤其是将 window 函数混入其中时。
Teradata 中没有LAG
,但您可以重写它:
SELECT
t.*
, (time)
- min(time)
OVER (PARTITION BY cust_id
ORDER BY time
ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) SECOND(4)
FROM
table_01 as t
当您尝试获取秒数时,您会遇到 "Interval Overflow" 错误,即超过 9999 秒。要么更改为 DAY(4) TO SECOND
,要么使用我几年前写的这个 SQL UDF,用于计算两个时间戳的秒数之差:
REPLACE FUNCTION TimeStamp_Diff_Seconds
(
ts1 TIMESTAMP(6)
,ts2 TIMESTAMP(6)
)
RETURNS DECIMAL(18,6)
LANGUAGE SQL
CONTAINS SQL
RETURNS NULL ON NULL INPUT
DETERMINISTIC
SQL SECURITY DEFINER
COLLATION INVOKER
INLINE TYPE 1
RETURN
(CAST((CAST(ts2 AS DATE)- CAST(ts1 AS DATE)) AS DECIMAL(18,6)) * 60*60*24)
+ ((EXTRACT( HOUR FROM ts2) - EXTRACT( HOUR FROM ts1)) * 60*60)
+ ((EXTRACT(MINUTE FROM ts2) - EXTRACT(MINUTE FROM ts1)) * 60)
+ (EXTRACT(SECOND FROM ts2) - EXTRACT(SECOND FROM ts1))
;