基于其他列值的聚合

时间:2014-03-15 11:30:11

标签: sql oracle

假设我有下表:

+------------+-------------+
| Product_id | customer_id |
+------------+-------------+
| a          | c1          |
| a          | c2          |
| a          | c3          |
| a          | c4          |
| b          | c1          |
| c          | c1          |
| b          | c2          |
| d          | c2          |
+------------+-------------+

我想查找每位客户购买的(a,b,c)产品数量以及每位客户购买的(a,b,d)产品数量。我尝试将COUNTGROUP BY一起使用,但我只设法找到每个客户FIDDLE的购买数量。我需要使用CASE WHEN还是DECODE?我怎样才能做到这一点?

预期输出类似于:

+-------------+-------------+-------------+
| CUSTOMER_ID | ABC_PRODUCT | ABD_PRODUCT |
+-------------+-------------+-------------+
| c1          |           1 |           0 |
| c2          |           0 |           1 |
| c3          |           0 |           0 |
| c4          |           0 |           0 |
+-------------+-------------+-------------+

4 个答案:

答案 0 :(得分:2)

您可以使用单个聚合而不使用子查询来执行此操作。关键是使用带有聚合的嵌套case语句来计算每个客户的每个产品。以下内容确定客户是否拥有每个“捆绑”:

SELECT CUSTOMER_ID,
       (case when max(case when product_id = 'a' then 1 else 0 end) +
                  max(case when product_id = 'b' then 1 else 0 end) +
                  max(case when product_id = 'c' then 1 else 0 end) = 3
             then 1
             else 0
        end) as ABC,
       (case when max(case when product_id = 'a' then 1 else 0 end) +
                  max(case when product_id = 'b' then 1 else 0 end) +
                  max(case when product_id = 'd' then 1 else 0 end) = 3
             then 1
             else 0
        end) as ABD           
FROM CUSTOMERS_SALES
GROUP BY CUSTOMER_ID;

现在,您的问题实际上是关于此类购买的数量。所以,我想客户可以两次购买每件商品,你会希望他们计算两次。如果是,那么该数字是任何计数的最小值。你也可以这样做:

SELECT CUSTOMER_ID,
       least(sum(case when product_id = 'a' then 1 else 0 end),
             sum(case when product_id = 'b' then 1 else 0 end),
             sum(case when product_id = 'c' then 1 else 0 end) 
            ) as ABC,
       least(sum(case when product_id = 'a' then 1 else 0 end),
             sum(case when product_id = 'b' then 1 else 0 end),
             sum(case when product_id = 'd' then 1 else 0 end) 
            ) as ABD
FROM CUSTOMERS_SALES
GROUP BY CUSTOMER_ID;

答案 1 :(得分:1)

请尝试以下查询,找到拥有产品a, b and c的客户:

SELECT CUSTOMER_ID
FROM CUSTOMERS_SALES
WHERE PRODUCT_ID IN ('a', 'b', 'c') 
GROUP BY CUSTOMER_ID
HAVING COUNT(DISTINCT PRODUCT_ID)=3

要获得点数,请尝试

SELECT COUNT(*) FROM(
  SELECT CUSTOMER_ID
  FROM CUSTOMERS_SALES
  WHERE PRODUCT_ID IN ('a', 'b', 'd')
  GROUP BY CUSTOMER_ID
  HAVING COUNT(DISTINCT PRODUCT_ID)=3
)x

答案 2 :(得分:0)

完全基于@ TechDo的例子:

SELECT DISTINCT CUSTOMER_ID, 
       DECODE((SELECT CUSTOMER_ID
                 FROM CUSTOMERS_SALES CS2
                WHERE PRODUCT_ID IN ('A', 'B', 'C') 
                  AND CS2.CUSTOMER_ID = CS.CUSTOMER_ID
               GROUP BY CUSTOMER_ID
               HAVING COUNT(DISTINCT PRODUCT_ID)=3), NULL, 0, 1) AS ABC_PRODUCT,
       DECODE((SELECT CUSTOMER_ID
                 FROM CUSTOMERS_SALES CS2
                WHERE PRODUCT_ID IN ('A', 'B', 'D') 
                  AND CS2.CUSTOMER_ID = CS.CUSTOMER_ID
               GROUP BY CUSTOMER_ID
               HAVING COUNT(DISTINCT PRODUCT_ID)=3), NULL, 0, 1) AS ABD_PRODUCT
  FROM CUSTOMERS_SALES CS
ORDER BY CUSTOMER_ID

答案 3 :(得分:0)

SELECT CUSTOMERS_SALES.CUSTOMER_ID,NVL(MAX(abc.CUSTOMER_ID),0) as ABC_PRODUCT ,NVL(MAX(abd.CUSTOMER_ID),0) as ABD_PRODUCT  FROM CUSTOMERS_SALES 
 LEFT JOIN
(SELECT CUSTOMER_ID 
  FROM CUSTOMERS_SALES
  WHERE PRODUCT_ID IN ('a', 'b', 'd')
  GROUP BY CUSTOMER_ID
  HAVING COUNT(DISTINCT PRODUCT_ID)=3) abd
ON abd.CUSTOMER_ID=CUSTOMERS_SALES.CUSTOMER_ID
 LEFT JOIN
(SELECT CUSTOMER_ID 
  FROM CUSTOMERS_SALES
  WHERE PRODUCT_ID IN ('a', 'b', 'c')
  GROUP BY CUSTOMER_ID
  HAVING COUNT(DISTINCT PRODUCT_ID)=3) abc
ON abc.CUSTOMER_ID=CUSTOMERS_SALES.CUSTOMER_ID
GROUP BY CUSTOMERS_SALES.CUSTOMER_ID
ORDER BY CUSTOMERS_SALES.CUSTOMER_ID;

FIDDLE