SQL中的互斥计数

时间:2017-09-25 02:08:45

标签: sql sql-server ssms

我需要查询的表格如下所示

ID - Account - Product

1  - 002     - Bike         
2  - 003     - Bike         
4  - 003     - Motor        
5  - 004     - Car       

我需要能够检索购买每种产品和产品组合的帐户数量,例如

Bike | Car | Motor | Bike&Car | Bike&Motor | Car&Motor | Bike&Car&Motor

请注意,购买产品组合的帐户将被计为1.

请帮我检索这些数据。

2 个答案:

答案 0 :(得分:0)

您可以使用两个级别的聚合来执行此操作。一种方法将值放在不同的行上:

select has_bike, has_motor, has_car, count(*)
from (select account,
             max(case when product = 'bike' then 1 else 0 end) as has_bike,
             max(case when product = 'motor' then 1 else 0 end) as has_motor,
             max(case when product = 'car' then 1 else 0 end) as has_car
      from t
      group by account
     ) t
group by has_bike, has_motor, has_car;

或在列中:

select sum(has_bike * (1 - has_motor) * (1 - has_car)) as has_only_bike,
       sum((1 - has_bike) * has_motor * (1 - has_car)) as has_only_motor,
       sum((1 - has_bike) * (1 - has_motor) * has_car) as has_only_car,
       . . .
from (select account,
             max(case when product = 'bike' then 1 else 0 end) as has_bike,
             max(case when product = 'motor' then 1 else 0 end) as has_motor,
             max(case when product = 'car' then 1 else 0 end) as has_car
      from t
      group by account
     ) t;

答案 1 :(得分:0)

如果您只有一组有限的Product,那么您可以使用:

-- Create sample data
CREATE TABLE #tbl(
    ID      INT,
    Account VARCHAR(10),
    Product VARCHAR(10)
);

INSERT INTO #tbl VALUES
(1, '002', 'Bike'),
(2, '003', 'Bike'),
(3, '003', 'Motor'),
(4, '004', 'Car');

WITH Cte AS(
    SELECT t1.Account, a.Products
    FROM #tbl t1
    CROSS APPLY (
        SELECT STUFF((
            SELECT '&' + t2.Product
            FROM #tbl t2
            WHERE t2.Account = t1.Account
            ORDER BY t2.Product
            FOR XML PATH(''), type).value('.[1]','nvarchar(max)'),
        1, 1, '')  AS Products
    ) a
    GROUP BY t1.Account, a.Products
)
SELECT
    Bike                = SUM(CASE WHEN Products = 'Bike' THEN 1 ELSE 0 END),
    Car                 = SUM(CASE WHEN Products = 'Car' THEN 1 ELSE 0 END),
    Motor               = SUM(CASE WHEN Products = 'Motor' THEN 1 ELSE 0 END),
    [Bike&Car]          = SUM(CASE WHEN Products = 'Bike&Car' THEN 1 ELSE 0 END),
    [Bike&Motor]        = SUM(CASE WHEN Products = 'Bike&Motor' THEN 1 ELSE 0 END),
    [Car&Motor]         = SUM(CASE WHEN Products = 'Car&Motor' THEN 1 ELSE 0 END),
    [Bike&Car&Motor]    = SUM(CASE WHEN Products = 'Bike&Car&Motor' THEN 1 ELSE 0 END)
FROM Cte;

DROP TABLE #tbl; -- Remove sample data

我们的想法是为每个Account生成一行,以及逗号分隔的Products。如果您在CTE中执行查询,您将获得:

Account    Products
---------- ---------------
002        Bike
003        Bike&Motor
004        Car

有了它,你可以进行条件聚合。以上使用静态解决方案,如果您不知道Product的数量,则可能需要采用动态方法。

ONLINE DEMO