Selecting rows with constrained time-stamp differences (in seconds) in tables in SQL

余生长醉 提交于 2020-11-29 21:29:51

问题


I have a table called visit_times in SQL like this

    name   time_stamp
    Allen  2015-02-13 07:10:54
    Allen  2015-02-13 07:10:58
    Allen  2015-02-13 07:11:02
    Mary   2015-02-17 10:45:33
    Mary   2015-02-17 10:45:39
    Mary   2015-02-17 10:45:43
    ...    

I need to select names from "name" column for which all the row-consecutive differences (in second) in the "time_stamp" column equals a certain value. Using the LAG() command I have tried to code it up as follows

WITH cte AS
(
  SELECT  name, 
          DATEDIFF(second, LAG(time_stamp) OVER (PARTITION BY name ORDER BY time_stamp), time_stamp) AS visit_gap 
  FROM customer_transactions
)
SELECT cte.name
FROM cte
GROUP BY cte.name
HAVING MIN(cte.visit_gap) = 10 AND MAX(cte.visit_gap) = 4;

I expect to get the result as follows:

---------
| name  |
---------
| Allen |
---------

But it outputs nothing! I get the error: in the pre-written template: Incorrect parameter count in the call to native function 'DATEDIFF'

I am not sure how to fix this. Any hints would be appreciated.


回答1:


SQL queries are processed in a certain order (a quick search for "sql query order of operations" gave me this nice result). The column alias visit_gap can only be reused starting from the order by clause. This explains your syntax error.

The usual solution would be to duplicate the visit_gap expression in the where clause giving you this:

SELECT  name, 
        time_stamp - LAG(time_stamp) OVER (PARTITION BY name ORDER BY time_stamp) AS visit_gap
FROM visit_times
WHERE time_stamp - LAG(time_stamp) OVER (PARTITION BY name ORDER BY time_stamp) = 4;

However, this will give you a new error that states that the LAG() function cannot appear in the where clause...

Windowed functions can only appear in the SELECT or ORDER BY clauses.

In order to separate the LAG() or visit_gap calculation and the filtering (where clause) you could use a common table expression (CTE). Also, use the DATEDIFF() function (function documentation) to calculate the difference between dates.

with cte as
(
  SELECT  name, 
          datediff(second, LAG(time_stamp) OVER (PARTITION BY name ORDER BY time_stamp), time_stamp) AS visit_gap
  FROM visit_times
)
select cte.name,
       cte.visit_gap --> column alias is available now!
from cte;

Adding a filter in the where clause gives you your final result:

with cte as
(
  SELECT  name, 
          datediff(second, LAG(time_stamp) OVER (PARTITION BY name ORDER BY time_stamp), time_stamp) AS visit_gap
  FROM visit_times
)
select cte.name,
       cte.visit_gap --> column alias is available now!
from cte
where cte.visit_gap > 4;

Fiddle with all intermediate steps explained!



来源:https://stackoverflow.com/questions/64763111/selecting-rows-with-constrained-time-stamp-differences-in-seconds-in-tables-in

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!