SQL 查询 - 如何使用 group by 获取 2 行或更多行

Posted

技术标签:

【中文标题】SQL 查询 - 如何使用 group by 获取 2 行或更多行【英文标题】:SQL query - how to get 2 or more rows with group by 【发布时间】:2017-02-15 23:40:18 【问题描述】:

我有两张桌子。一个是带有列的客户表:cid、name、state。 另一个表是 Purchase 表,列有:pid、cid、booktitle、price。

客户:

CID    NAME    STATE
1      Peng    NY
2      Li      IL
3      Chan    NY

购买:

PID CID BOOKTITLE PRICE
10  1   ABC       20 
11  3   XYZ       15 
12  1   MNOP      12

输出:

STATE CID  NAME 
NY    1    Peng
IL    null null

我需要输出每个州购买量最高(最大订单)的客户的 cid 和名称。我可以为每个客户输出 cid、姓名、状态和购买次数,但不能为每个状态获取它,因为在使用 group by 函数时我不能使用更多列:

select c.cid, c.name, c.state, d.orders 
from customer c
left join (select cid, count(pid) as orders 
           from purchase
           group by cid) d
on c.cid = d.cid;

谁能建议我应该如何进行?

【问题讨论】:

您在谈论“最大订单”,但在 ORDERS 表中您只有一个 PRICE 列。你的意思是“最高价格”吗?另外,如果在一个州有两个或多个客户以最高价格捆绑,您希望退回什么?将它们都(全部)归还?或者只是其中一个,随机的? 没有。不是价格。我的意思是最大订单数。意思是,客户完成的最大购买量。 对于第二部分,如果出现平局,随机客户或两者(全部)都有效。任何输出都是可以接受的。谢谢 您的问题不清楚。根据您上面的措辞,您需要按州分组的 cid 和客户名称,但您已经拥有 cid、客户名称、州和订单数量。请更具体地说明您的问题,并提供您预期输出的示例表。 @EdwardRusu 对不起,我是新手。我没有订单数量。我只有一个名为 purchase 的表,它记录了各个客户下的单个订单。我已经给出了上面的输出表。也许你没看到。请告诉我还有什么需要澄清的。 【参考方案1】:

您可以将窗口函数与聚合函数结合起来:

select cp.*
from (select c.cid, c.name, c.state, count(p.cid) as orders,
             row_number() over (partition by c.state order by count(p.cid) desc) as seqnum
      from customer c left join
           purchase p
           on c.cid = p.cid
      group by c.cid, c.name, c.state
     ) cp
where seqnum = 1;

您要查找的值称为mode。如果您想要给定状态的所有模式,请使用 rank()dense_rank() 而不是 row_number()

【讨论】:

连接应该在 c.cid = p.cid;无论如何,这不会将 IL 作为结果的一部分。 @gregory 。 . .我认为只需要left join 而不是join【参考方案2】:
with cnt as (
select c.state, c.name, c.cid, count(p.cid) orders from customer c  
left outer join purchase p on p.cid = c.cid
group by c.state, c.name, c.cid )
select state, 
case when orders=0 then null else cid end cid, 
case when orders=0 then null else name end name 
from (select state, name, cid, orders, 
      row_number() over (partition by state order by orders desc) rn
      from cnt)
order by name, state;

结果:

STATE             CID NAME
---------- ---------- ----------
NY                  1 Peng
IL

【讨论】:

谢谢。这就是我一直在寻找的。我没有意识到我可以用分析函数解决这个问题。【参考方案3】:
WITH
    orders AS
    (   -- enumerate the values by buckets of state 
        -- ordered by num_orders per state
        SELECT
            ROW_NUMBER() OVER (PARTITION BY state ORDER BY num_orders DESC) rn
            , state
            , cid
            , num_orders
        FROM
        (   -- calculate counts by state and customer id
            SELECT
                c.state
                , p.cid
                , COUNT(p.pid) as num_orders
            FROM        purchase p
            INNER JOIN  customer c ON p.cid = c.cid
            GROUP BY    
                c.state
                , p.cid
        )

    )
-- return desired values
SELECT
    c.state
    , c.cid
    c.name
FROM        customer    c
LEFT JOIN   orders      o 
ON 
    c.cid = o.cid 
    AND c.state = o.state
    AND rn = 1

【讨论】:

以上是关于SQL 查询 - 如何使用 group by 获取 2 行或更多行的主要内容,如果未能解决你的问题,请参考以下文章

如何在linq C#中使用group by并获取记录列表[重复]

mysql在group by之后如何获取每一组中id最大的那一行

如何在 laravel 中使用 concat 和 group by?

SQL - 使用 GROUP BY 获取子查询子集中或连接中的最新记录

使用 group by 和条件优化 SQL 查询

mysql在group by之后如何获取每一组中id最大的那一行