在SQL中的表中选择具有受限时间戳差异以秒为单位的行

问题描述

我在sql中有一个名为visit_times的表,

    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
    ...    

我需要从“名称”列中选择名称,对于这些名称,“ time_stamp”列中的行连续差异(秒)等于某个值。使用LAG()命令,我尝试如下进行编码

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;

我希望得到如下结果:

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

但是它什么也没输出!我收到错误消息:在预写的模板中:对本机函数'DATEDIFF'的调用中参数计数不正确

我不确定如何解决此问题。任何提示将不胜感激。

解决方法

SQL查询以一定顺序进行处理(快速搜索“ SQL查询操作顺序”给了我nice result)。列别名visit_gap仅可从order by子句开始重用。这说明了您的语法错误。

通常的解决方案是在visit_gap子句中复制where表达式,从而为您提供:

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;

但是,这将给您带来一个新错误,该错误指出LAG()函数不能出现在where子句中...

窗口函数只能出现在SELECT或ORDER BY子句中。

为了分开LAG()visit_gap计算和过滤(where子句),可以使用common table expression(CTE)。另外,使用DATEDIFF()函数(function documentation)计算日期之间的差。

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子句中添加过滤器可为您提供最终结果:

with cte as
(
  SELECT  name,cte.visit_gap --> column alias is available now!
from cte
where cte.visit_gap > 4;

Fiddle,并解释了所有中间步骤!