簡體   English   中英

使用case語句的項目數量不同

[英]distinct count of items using case statements

我無法獲得購買了商品A和B的客戶數量。 以下是我正在使用的數據示例。

Customer No | Item
___________________
 1            A
 1            B
 2            B
 3            A
 4            A
 4            B
 5            B
 6            A

我正在嘗試計算有多少客戶購買了商品A和B。這是我到目前為止所嘗試的。 我得到以下結果項目A = 5,項目B = 3以及項目A和B = 6。

Select 
count (distinct case when ItemNo = 'A' then customerNo end) as [A],
count (distinct case when ItemNo = 'B' then customerNo end) as [B],
count (distinct case when (ItemNo = 'A' or ItemNo = 'B') then customerNo end) as [AandB]
from Items

這是我想要得到的結果:

Item | Count
A             4
B             4
A and B       2

有人可以指出我正確的方向以獲得此結果。 謝謝!

我認為您的預期結果可能是A = 4B = 4

您可以嘗試使用UNION ALL來獲取AB以及A & B金額。

SELECT ItemNo,COUNT(distinct customerNo) Count
FROM Items
GROUP BY ItemNo
UNION ALL
SELECT 'A and B',count(*)
FROM (
    SELECT COUNT(DISTINCT ItemNo) cnt
    FROM Items tt
    WHERE ItemNo IN ('A','B') 
    GROUP BY [CustomerNo]
    HAVING COUNT(DISTINCT ItemNo) = 2
) t1

這是另一種方法。

SQL Server有一個有用的運算符INTERSECT ,這正是您在這里需要的-兩個集合的相交(買A人和買B )。

我認為它比使用HAVING過濾器進行模糊分組更具可讀性。

在性能方面,您應該在真實數據上嘗試所有變體。

樣本數據

DECLARE @T TABLE (CustomerNo int, Item varchar(50));
INSERT INTO @T (CustomerNo, Item) VALUES
(1, 'A'),
(1, 'B'),
(2, 'B'),
(3, 'A'),
(4, 'A'),
(4, 'B'),
(5, 'B'),
(6, 'A');

詢問

SELECT
    Item
    ,COUNT(DISTINCT CustomerNo) AS CustomerCount
    ,0 AS SortOrder
FROM @T
GROUP BY Item

UNION ALL

SELECT
    'A & B' AS Item
    ,COUNT(*) AS CustomerCount
    ,1 AS SortOrder
FROM
(
    SELECT CustomerNo
    FROM @T
    WHERE Item = 'A'

    INTERSECT

    SELECT CustomerNo
    FROM @T
    WHERE Item = 'B'
) AS T

ORDER BY SortOrder, Item
;

查詢的第一部分通過對Item進行簡單分組來統計客戶。 查詢的第二部分(在UNION ALL )計算同時購買AB那些客戶。

SortOrder列只是為了適當地排序最終結果。

結果

+-------+---------------+-----------+
| Item  | CustomerCount | SortOrder |
+-------+---------------+-----------+
| A     |             4 |         0 |
| B     |             4 |         0 |
| A & B |             2 |         1 |
+-------+---------------+-----------+
select count (distinct case when I.ItemNo = 'A' then customerNo end) as A, 
       count (distinct case when I.ItemNo = 'B' then customerNo end) as B, 
       count (distinct case when (I.ItemNo = 'A' and (select count(*) from items as I2 where I2.itemno = 'B' and I.customerNo = I2.customerNo ) > 0) 
       then customerNo end) as AB 
from Items as I;

您不希望在最后一個COUNT中使用“ OR”條件,而是要使用“ AND”。 在這里,我使用相關子查詢來計算同一客戶(I.customerNo = I2.customerNo)訂購itemno'B'(I2.itemno ='B')的行數。 如果計數> 0,則客戶訂購了物料A和B。

相關子查詢由I.customerNo = I2.customerNo條件建立。

如果您無法在COUNT中執行子查詢,則這是一種較長的方法,也可以使用

SELECT SUM(D.A), SUM(D.B), SUM(D.AB) FROM
(
    select A, B, case when U.A > 0 AND U.B > 0 THEN 1 end AS AB
    from (
        select count (distinct case when I.ItemNo = 'A' then customerNo end) as A, 
               count (distinct case when I.ItemNo = 'B' then customerNo end) as B
        from Items as I
        group by I.customerNo
    ) AS U
) AS D;

這是一種方法。 我們可以先嘗試按客戶進行匯總以生成A和B計數。 然后,匯總這些計數。

WITH cte AS (
    SELECT customerNo,
        COUNT(CASE WHEN Item = 'A' THEN 1 END) AS a_cnt,
        COUNT(CASE WHEN Item = 'B' THEN 1 END) AS b_cnt
    FROM Items
    GROUP BY customerNo
)

SELECT 'A' AS Item, COUNT(CASE WHEN a_cnt > 0 THEN 1 END) AS Count, 0 AS pos FROM cte
UNION ALL
SELECT 'B', COUNT(CASE WHEN b_cnt > 0 THEN 1 END), 1 FROM cte
UNION ALL
SELECT 'A and B', COUNT(CASE WHEN a_cnt > 0 AND b_cnt > 0 THEN 1 END), 2 FROM cte
ORDER BY pos;

我將通過兩個聚合級別來做到這一點:

select sum(has_a) as num_A,
       sum(has_b) as num_B,
       sum(has_a * has_b) as num_AB
from (select i.customer,
             max(case when item_no = 'A' then 1 else 0 end) as has_A,
             max(case when item_no = 'B' then 1 else 0 end) as has_B
      from items
      group by i.customer
     ) ic;

您還可以在不同的行上獲取此信息:

select has_a, has_b, count(*)
from (select i.customer,
             max(case when item_no = 'A' then 1 else 0 end) as has_A,
             max(case when item_no = 'B' then 1 else 0 end) as has_B
      from items
      group by i.customer
     ) ic
group by has_A, has_B;

這並不完全相同,因為這些值僅適用於產品組合。 換句話說,每個客戶只計算一次。 我喜歡的是:

  • 很容易擴展到更多產品和組合。
  • 您可以更改子查詢並具有計數而不是標志。
  • 客戶只計算一次。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM