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

时间:2017-02-15 23:40:19

标签: sql oracle

我有两张桌子。一个是带有列的客户表:cid,名称,状态。 另一个表是带有列的购买表:pid,cid,booktitle,price。

CUSTOMER:

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

PURCHASE:

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,名称,状态和购买次数,但不能为每个州输出,因为我在使用按功能分组时无法使用更多列:

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;

有人可以建议我该怎么办?

3 个答案:

答案 0 :(得分: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()

答案 1 :(得分:0)

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

答案 2 :(得分:0)

setup.py

结果:

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;