Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

sql - Time difference in hours and seconds over a partition window in Teradata (Sessionizing Records)

Given a table like this:

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

I would like to calculate the time difference between each preceding record (think lag function) by cust_id. My desired output:

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

How do I accomplish this in Teradata?

I have tried stuff like:

SELECT
  *
  , (time - time) OVER (PARTITION BY cust_id ORDER BY time ROWS BETWEEN 1 PRECEDING AND CURRENT ROW)
FROM
  table_01

However, while the NULLs show up where expected, I keep receive 0.0 for all other results. I have also tried using wrapping (time - time) with SUM and I have tried using EXTRACT(SECOND FROM TIME) and a few other variants -- e.g., trying to place DAY(4) to SECOND, but I can't seem to get the syntax/ordering/conversion quite right, especially when tossing a window function into the mix.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

There's no LAG in Teradata, but you can rewrite it:

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

When you try to get seconds you will encouter "Interval Overflow" errors, i.e. more than 9999 seconds. Either change to DAY(4) TO SECOND or use this SQL UDF I wrote a few years ago for calculating the difference of two timestamps in seconds:

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))
;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...