Postgresql为每位客户返回最流行的产品类型

时间:2016-03-31 02:05:35

标签: sql postgresql

我有一个查询应该返回每个客户最热门产品类型的客户列表。我有一个查询,总结了在所有给定产品类型中购买的每个产品,并按每个客户的降序列出

SELECT c.customer_name as cname, ptr.product_type as pop_gen, sum(od.quantity) as li
FROM product_type_ref as ptr
INNER JOIN product as p 
    on p.product_type_ref_id = ptr.product_type_ref_id
INNER JOIN order_detail as od
    on od.product_id = p.product_id
INNER JOIN order as o
    on o.order_id = od.order_id
INNER JOIN customer as c 
    on c.customer_id = o.customer_id
GROUP BY cname, pop_gen
ORDER BY cname, li DESC

返回此数据:

'andy','Drama',1000
'andy','Action',250
'andy','Comedy',100
'bebe','Drama',250
'bebe','Action',100
'bebe','Comedy',25
'buster','Action',825
'buster','Comedy',768
'buster','Drama',721
'buster','Romance',100
'ron','Romance',50
'ron','Comedy',10

我怎么能回复这个:

andy, Drama
bebe, Drama
buster, Action
ron, Romance

3 个答案:

答案 0 :(得分:1)

在Postgres中,您可以使用distinct on

SELECT DISTINCT ON (c.customer_name) c.customer_name as cname,
       ptr.product_type as pop_gen, sum(od.quantity) as li
FROM product_type_ref as ptr
INNER JOIN product as p 
    on p.product_type_ref_id = ptr.product_type_ref_id
INNER JOIN order_detail as od
    on od.product_id = p.product_id
INNER JOIN order as o
    on o.order_id = od.order_id
INNER JOIN customer as c 
    on c.customer_id = o.customer_id
GROUP BY cname, pop_gen
ORDER BY cname, li DESC;

答案 1 :(得分:0)

添加ROW_NUMBER()

SELECT *
FROM (
        SELECT c.customer_name as cname, 
               ptr.product_type as pop_gen, 
               sum(od.quantity) as li,
               ROW_NUMBER() OVER (PARTITION BY c.customer_name
                                  ORDER BY sum(od.quantity) DESC) as rn
       ......
     ) as T
WHERE T.rn = 1

答案 2 :(得分:0)

经典greatest-n-per-group。一种可能的解决方案是使用ROW_NUMBER()

WITH
CTE
AS
(
    SELECT 
        c.customer_name as cname, ptr.product_type as pop_gen, sum(od.quantity) as li
        ,ROW_NUMBER() OVER(PARTITION BY c.customer_name ORDER BY sum(od.quantity) DESC) AS rn
    FROM 
        product_type_ref as ptr
        INNER JOIN product as p on p.product_type_ref_id = ptr.product_type_ref_id
        INNER JOIN order_detail as od on od.product_id = p.product_id
        INNER JOIN order as o on o.order_id = od.order_id
        INNER JOIN customer as c on c.customer_id = o.customer_id
    GROUP BY 
        cname, pop_gen
)
SELECT
    cname, pop_gen, li
FROM CTE
WHERE rn = 1
ORDER BY cname;