You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何过滤SQL结果,实现每个客户仅保留一条商品记录(甜瓜优先)

解决方案:筛选客户商品购买记录

针对你的需求——同时购买Melon和Rice的客户仅保留Melon记录,仅购买其中一种的保留对应商品记录,这里提供几种可行的实现方式,同时解答你关于HAVING子句使用CASE的疑问:

方法一:窗口函数(推荐)

利用ROW_NUMBER()窗口函数给商品设置优先级,Melon优先级高于Rice,再取每个客户的第一条记录:

WITH ranked_products AS (
    SELECT 
        CustomerId,
        Name,
        Product,
        Price,
        -- 给Melon标记优先级1,Rice标记2,按客户分组排序
        ROW_NUMBER() OVER (PARTITION BY CustomerId, Name ORDER BY CASE WHEN Product = 'Melon' THEN 1 ELSE 2 END) AS rn
    FROM LIST
    WHERE Product IN ('Melon', 'Rice') -- 仅筛选目标商品
)
SELECT CustomerId, Name, Product, Price
FROM ranked_products
WHERE rn = 1;

逻辑说明:每个客户的记录组内,Melon会排在最前面,因此取rn=1就能保证同时买两种的客户只保留Melon,只买一种的保留对应商品。

方法二:UNION ALL + EXISTS子查询

分两部分查询后合并:先取所有Melon记录,再取未购买Melon的客户的Rice记录:

-- 取所有购买过Melon的记录
SELECT CustomerId, Name, Product, Price
FROM LIST
WHERE Product = 'Melon'

UNION ALL

-- 取仅购买Rice的客户记录(排除买过Melon的)
SELECT CustomerId, Name, Product, Price
FROM LIST
WHERE Product = 'Rice'
AND NOT EXISTS (
    SELECT 1
    FROM LIST AS L2
    WHERE L2.CustomerId = LIST.CustomerId
    AND L2.Name = LIST.Name
    AND L2.Product = 'Melon'
);

关于HAVING子句中使用CASE的问题

可以使用,但更适合在SELECT子句结合聚合函数来实现逻辑(HAVING主要用于分组后的过滤,这里需求不需要过滤分组,而是选择分组内的特定记录)。示例如下:

SELECT 
    CustomerId,
    Name,
    -- 判断客户是否买过Melon,有则取Melon,否则取Rice
    CASE WHEN COUNT(CASE WHEN Product = 'Melon' THEN 1 END) > 0 THEN 'Melon' ELSE 'Rice' END AS Product,
    -- 对应取Melon的价格,无则取Rice的价格
    COALESCE(MAX(CASE WHEN Product = 'Melon' THEN Price END), MAX(CASE WHEN Product = 'Rice' THEN Price END)) AS Price
FROM LIST
WHERE Product IN ('Melon', 'Rice')
GROUP BY CustomerId, Name;

逻辑说明:通过聚合函数统计客户是否有Melon记录,再用CASE选择对应的商品和价格,最终每个客户返回一条符合要求的记录。

内容的提问来源于stack exchange,提问作者Waren Schild

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 05:18:20