为啥在窗口函数中使用 GROUP BY
Posted
技术标签:
【中文标题】为啥在窗口函数中使用 GROUP BY【英文标题】:Why use GROUP BY in WINDOW FUNCTION为什么在窗口函数中使用 GROUP BY 【发布时间】:2021-03-19 22:32:24 【问题描述】:我目前正在使用 Northwind 数据库,希望看到 1997 年有更多订单的公司。我被要求使用 Windows 功能,所以我写了这个
select c.customerid,
c.companyname,
rank() over (order by count(orderid) desc )
from customers c
inner join orders o on c.customerid = o.customerid
where date_part('year',orderdate) = 1997;
但是,此代码要求我将 GROUP BY 与 c.customerid 一起使用。我根本不明白为什么。假设这段代码会给我所有的客户 id 和名称,然后窗口函数会根据订单数量给他们一个排名。那么为什么要对它们进行分组呢?
【问题讨论】:
【参考方案1】:这里:
rank() over (order by count(orderid) desc )
您在窗口函数 (count(orderid)
) 的 over()
子句中有一个聚合函数,因此您确实需要一个 group by
子句。您的想法是将同一客户的所有订单放在同一组中:
select c.customerid,
c.companyname,
rank() over (order by count(*) desc) as rn
from customers c
inner join orders o on c.customerid = o.customerid
where o.orderdate = date '1997-01-01' and o.orderdate < '1998-01-01'
group by c.customerid;
注意事项:
过滤文字日期比在日期列上应用日期函数更有效
count(orderid)
在此查询的上下文中等同于 count(*)
Postgres 理解函数依赖列:假设customerid
是customer
的主键,只需将该列放在group by
子句中就足够了
在select
子句中为表达式赋予别名是一种很好的做法
另一个好的做法是在所有列前面加上它们所属的表(别名)
【讨论】:
谢谢队友。我现在明白为什么 group by 需要在这里。也感谢您的提示!【参考方案2】:您可以在 聚合 查询中正确使用它。那将是:
select c.customerid, c.companyname, count(*) as num_orders,
rank() over (order by count(*) desc) as ranking
from customers c inner join
orders o
on c.customerid = o.customerid
where date_part('year',orderdate) = 1997
group by c.customerid, c.companyname;
这会计算 1997 年每位客户的订单数量。然后根据订单数量对客户进行排名。
我建议你使用:
where orderdate >= '1997-01-01' and
orderdate < '1998-01-01'
用于按年份过滤。这允许 Postgres 使用可用的索引。
【讨论】:
以上是关于为啥在窗口函数中使用 GROUP BY的主要内容,如果未能解决你的问题,请参考以下文章
在窗口函数中使用不在 Group By 中的列,我得到: SQL 编译错误:[COLUMN_A] is not a valid group by expression