【问题标题】:Why extra subquery needed for filtering out where clause? [duplicate]为什么需要额外的子查询来过滤 where 子句? [复制]
【发布时间】:2022-01-14 20:54:54
【问题描述】:

首先。抱歉标题含糊。我不知道如何构图。通过示例代码,希望你能理解我的疑惑。

任务是找出俱乐部中产生收入的前三项设施。 我以为这是最终代码。

 SELECT x,y as rank
    FROM tableA
 where rank <=3;

但这表示排名列不存在。所以我必须将它包含在另一个子查询中以过滤前 3 名。

 SELECT x,rank
    FROM
 (SELECT x,y as rank
    FROM tableA
 ) as sub
 where rank<=3;

为什么?我需要一个额外的子查询?为什么不能在原始查询中使用 where 子句进行过滤?

设施名称代码及其按收入排名:

select res.name,rank() over(order by total desc) as rank
    from
(select fac.facid,fac.name,sum(slots*
                case
                    when memid=0 then guestcost
                    else membercost
                    end) as total
    from cd.bookings bks
    inner join cd.facilities fac
        on bks.facid=fac.facid
    group by fac.facid
order by total desc) as res

我认为可行的方法:

select res.name,rank() over(order by total desc) as rank
    from
(select fac.facid,fac.name,sum(slots*
                case
                    when memid=0 then guestcost
                    else membercost
                    end) as total
    from cd.bookings bks
    inner join cd.facilities fac
        on bks.facid=fac.facid
    group by fac.facid
order by total desc) as res
where rank<=3;           

     (why this don't work??)

什么有效:

select name, rank
    from
(select res.name,rank() over(order by total desc) as rank
    from
(select fac.facid,fac.name,sum(slots*
                case
                    when memid=0 then guestcost
                    else membercost
                    end) as total
    from cd.bookings bks
    inner join cd.facilities fac
        on bks.facid=fac.facid
    group by fac.facid
order by total desc) as res) as sub
where rank <=3;

【问题讨论】:

  • 第一个查询不起作用的原因是因为你在where子句中直接使用了窗口函数,这是不允许的。但是,在最后一个查询中,您是在子查询中进行排名。
  • 您根本不能在同一级别的 WHERE 子句中使用列别名。这就是 SQL 语法的定义方式。

标签: sql postgresql column-alias


【解决方案1】:

考虑您的第一个查询版本:

SELECT x, RANK() OVER (ORDER BY y) rnk
FROM tableA
WHERE rnk <= 3;

这是不合法的,因为您不能在 WHERE 子句中使用别名,这些别名是在同一级别的 SELECT 中定义的。这里的问题是窗口函数执行通常执行last,在WHERE 子句中的过滤发生之前。相反,您需要计算子查询中的排名,然后对其进行过滤:

SELECT *
FROM
(
    SELECT x, RANK() OVER (ORDER BY y) rnk
    FROM tableA
) t
WHERE rnk <= 3;

请注意,某些版本的 SQL 确实允许在 QUALIFY 子句中使用窗口函数:

SELECT x, RANK() OVER (ORDER BY y) rnk
FROM tableA
QUALIFY RANK() OVER (ORDER BY y) <= 3;

但 Postgres 不支持 QUALIFY,因此您可能必须使用子查询选项。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-20
    • 1970-01-01
    • 1970-01-01
    • 2022-08-19
    • 2012-09-18
    • 2015-09-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多