【问题标题】: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 和名称,然后窗口函数会根据订单数量给他们一个排名。那么为什么要对它们进行分组呢?

【问题讨论】:

    标签: sql postgresql count aggregate-functions window-functions


    【解决方案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 理解函数依赖列:假设customeridcustomer 的主键,只需将该列放在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 使用可用的索引。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-16
      • 2021-12-09
      • 2016-09-14
      • 2021-10-12
      • 1970-01-01
      相关资源
      最近更新 更多