where 子句是先运行,然后是解析函数,或者具体是如何在下面的查询中执行的?

Posted

技术标签:

【中文标题】where 子句是先运行,然后是解析函数,或者具体是如何在下面的查询中执行的?【英文标题】:Does where clause run first and then the analytical function or how does the execution takes place in below query specifically? 【发布时间】:2021-02-14 00:34:02 【问题描述】:
WITH conversions AS (
SELECT 
    *
FROM attribution a JOIN user_sessions u ON a.session_id = u.session_id
WHERE conversion = TRUE)

SELECT 
       user_id,
       **ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at END) AS rnk,**
       channel
FROM attribution a JOIN user_sessions u ON a.session_id = u.session_id
WHERE user_id IN (SELECT DISTINCT user_id FROM conversions) 
**AND rnk = 1**

我的困惑在于以下两点: 1 - 如果 Where 子句首先运行,我们只有选择性的 User_ids 来运行 row_number() 分析函数。那么我们如何在这里使用 rnk = 1 2 - 如果我们首先运行 row_number() 则意味着它正在对每个 user_id 进行排名,而与 WHERE 子句无关。这是正确的吗?

以上两种说法哪个更有意义?

【问题讨论】:

【参考方案1】:

从概念上讲,窗口函数只看到在where 子句中过滤后 保留的行。一个推论是您不能在 where 子句中使用窗口函数,正如您在此处尝试的那样(这是一个语法错误)。

我在您的代码中完全看不到 with 子句的意义。想必你想要的查询是:

select *
from (
    select user_id, channel,
        row_number() over(partition by user_id order by created_at) rn
    from attribution a
    inner join user_sessions u on u.session_id = u.session_id
    where conversion = true
) t
where rn = 1

我强烈建议在查询中的每一列前面加上它所属表的别名,这样查询对于底层数据结构是明确的。

【讨论】:

感谢@GMB 的快速回复。此处不使用 with 子句是有意义的。我只是想确保我的理解是正确的,当我们在 Where 子句中使用 rnk 时,上面的查询是错误的。谢谢

以上是关于where 子句是先运行,然后是解析函数,或者具体是如何在下面的查询中执行的?的主要内容,如果未能解决你的问题,请参考以下文章

为啥聚集函数不能出现在where子句中

删除 where 子句然后添加回来时的执行计划优化

使用有点奇怪的where子句的sql查询性能

SQL中的WHERE子句中为啥不允许应用聚集函数呢?请通俗的解释一下或者谈谈自己的见解!

WHERE 子句中的 CASE

WHERE 谓词的顺序和 SQL 优化器