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

去除SQL购物篮商品组合查询结果中的重复组合

解决购物篮商品组合重复计数的问题

你的问题核心是同一商品组合因列顺序不同被视为不同分组,导致重复统计。以下是三种可行的解决方法,按性能优化程度排序:

方法一:从JOIN阶段避免生成重复排列(最推荐)

直接在JOIN条件中强制SKU的顺序,让每个组合只以一种固定顺序出现,从源头消除重复:

WITH cte AS (
    SELECT 
        a.order_id, 
        a.SKU_number as product_1, 
        b.SKU_number as product_2, 
        c.SKU_number as product_3, 
        d.SKU_number as product_4
    FROM [cons_customer].[sales_detail_time] a
    JOIN [cons_customer].[sales_detail_time] b
        ON a.order_id = b.order_id AND b.SKU_number > a.SKU_number
    JOIN [cons_customer].[sales_detail_time] c
        ON a.order_id = c.order_id AND c.SKU_number > b.SKU_number
    JOIN [cons_customer].[sales_detail_time] d
        ON a.order_id = d.order_id AND d.SKU_number > c.SKU_number
    WHERE a.SKU_number = 'PBPR108BAU.H01'
)
SELECT TOP 50 
    product_2, 
    product_3, 
    product_4, 
    COUNT(*) AS count
FROM cte
GROUP BY product_2, product_3, product_4
ORDER BY count DESC;

原理

将原JOIN条件中的a.SKU_number <> b.SKU_number替换为b.SKU_number > a.SKU_number,强制后续关联的SKU必须比前一个字典序更大。这样每个商品组合只会以升序排列的形式出现在结果中,不会产生不同顺序的重复记录,后续分组统计自然准确。

方法二:通过排序函数统一组合顺序

如果无法修改JOIN条件,可在分组前对每个组合的SKU进行排序,生成固定顺序的列后再分组:

WITH cte AS (
    SELECT 
        a.order_id, 
        a.SKU_number as product_1, 
        b.SKU_number as product_2, 
        c.SKU_number as product_3, 
        d.SKU_number as product_4
    FROM [cons_customer].[sales_detail_time] a
    JOIN [cons_customer].[sales_detail_time] b
        ON a.order_id = b.order_id AND a.SKU_number <> b.SKU_number
    JOIN [cons_customer].[sales_detail_time] c
        ON a.order_id = c.order_id AND a.SKU_number <> c.SKU_number AND b.SKU_number <> c.SKU_number
    JOIN [cons_customer].[sales_detail_time] d
        ON a.order_id = d.order_id AND a.SKU_number <> d.SKU_number AND b.SKU_number <> d.SKU_number AND c.SKU_number <> d.SKU_number
    WHERE a.SKU_number = 'PBPR108BAU.H01'
),
sorted_items AS (
    SELECT 
        order_id,
        -- 提取三个商品的最小、中间、最大值,形成固定顺序
        LEAST(product_2, product_3, product_4) AS item_1,
        CASE
            WHEN (product_2 BETWEEN LEAST(product_2, product_3, product_4) AND GREATEST(product_2, product_3, product_4))
                 AND product_2 NOT IN (LEAST(product_2, product_3, product_4), GREATEST(product_2, product_3, product_4)) THEN product_2
            WHEN (product_3 BETWEEN LEAST(product_2, product_3, product_4) AND GREATEST(product_2, product_3, product_4))
                 AND product_3 NOT IN (LEAST(product_2, product_3, product_4), GREATEST(product_2, product_3, product_4)) THEN product_3
            ELSE product_4
        END AS item_2,
        GREATEST(product_2, product_3, product_4) AS item_3
    FROM cte
)
SELECT TOP 50 
    item_1, 
    item_2, 
    item_3, 
    COUNT(*) AS count
FROM sorted_items
GROUP BY item_1, item_2, item_3
ORDER BY count DESC;

原理

利用LEAST和GREATEST函数获取三个SKU的最小值和最大值,再通过CASE语句找出中间值,让同一组合的SKU始终以item_1 < item_2 < item_3的顺序排列,确保分组时相同组合会被归为一组。

方法三:用字符串拼接标识唯一组合

通过将三个SKU按顺序拼接成字符串,以该字符串作为分组依据,实现去重:

WITH cte AS (
    SELECT 
        a.order_id, 
        a.SKU_number as product_1, 
        b.SKU_number as product_2, 
        c.SKU_number as product_3, 
        d.SKU_number as product_4
    FROM [cons_customer].[sales_detail_time] a
    JOIN [cons_customer].[sales_detail_time] b
        ON a.order_id = b.order_id AND a.SKU_number <> b.SKU_number
    JOIN [cons_customer].[sales_detail_time] c
        ON a.order_id = c.order_id AND a.SKU_number <> c.SKU_number AND b.SKU_number <> c.SKU_number
    JOIN [cons_customer].[sales_detail_time] d
        ON a.order_id = d.order_id AND a.SKU_number <> d.SKU_number AND b.SKU_number <> d.SKU_number AND c.SKU_number <> d.SKU_number
    WHERE a.SKU_number = 'PBPR108BAU.H01'
),
combination_strings AS (
    SELECT 
        order_id,
        -- 按字典序拼接三个SKU,生成唯一标识
        STRING_AGG(sku, ',') WITHIN GROUP (ORDER BY sku) AS sorted_combination
    FROM (
        SELECT order_id, product_2 AS sku FROM cte
        UNION ALL
        SELECT order_id, product_3 AS sku FROM cte
        UNION ALL
        SELECT order_id, product_4 AS sku FROM cte
    ) t
    GROUP BY order_id
)
SELECT TOP 50 
    -- 将拼接字符串拆分为单独列(可选)
    PARSENAME(REPLACE(sorted_combination, ',', '.'), 3) AS item_1,
    PARSENAME(REPLACE(sorted_combination, ',', '.'), 2) AS item_2,
    PARSENAME(REPLACE(sorted_combination, ',', '.'), 1) AS item_3,
    COUNT(*) AS count
FROM combination_strings
GROUP BY sorted_combination
ORDER BY count DESC;

原理

先将三个SKU通过UNION ALL拆分成单条记录,再用STRING_AGG按字典序拼接成字符串——同一组合的拼接结果完全一致,以此作为分组键即可合并重复计数。最后可通过PARSENAME拆分字符串还原为单独列。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 03:01:05