创建计算列后必须使用子查询才能在WHERE子句中引用吗?
问题
我想基于login_date列创建一个名为Lag的计算列,将其滞后4天。是否可以直接用该列过滤数据表,还是必须通过子查询才能在WHERE子句中引用Lag列?
期望的写法(无法执行):
SELECT id, login_date, LAG(login_date, 4) OVER (PARTITION BY id ORDER BY login_date) as Lag FROM table WHERE DATEDIFF(Lag, login_date) = 4
希望避免的写法(实际可行):
SELECT sub.* FROM (SELECT id, login_date, LAG(login_date, 4) OVER (PARTITION BY id ORDER BY login_date) as Lag FROM table ) sub WHERE DATEDIFF(sub.lag, sub.login_date) = 4
解答
你不能直接在WHERE子句里引用窗口函数生成的别名列Lag。
SQL的执行顺序是先处理FROM和WHERE子句,再执行SELECT中的列计算(包括窗口函数)。也就是说,当WHERE子句运行时,Lag列还没有被计算出来,自然无法直接调用。
因此你必须借助子查询、CTE(公共表表达式)或者视图,先算出窗口函数的结果,再在外层查询中进行过滤。你给出的子查询写法是标准的可行方案,虽然多了一层嵌套,但这是符合SQL执行逻辑的必要操作。
另外,部分数据库(比如BigQuery、Snowflake)支持QUALIFY子句,用它可以直接过滤窗口函数的结果,写法更简洁:
SELECT id, login_date, LAG(login_date, 4) OVER (PARTITION BY id ORDER BY login_date) as Lag FROM table QUALIFY DATEDIFF(Lag, login_date) = 4
如果你的数据库支持这个语法,就能避开子查询了。
内容的提问来源于stack exchange,提问作者Katsu
相关产品推荐
相关产品推荐

