2011-06-04 24 views
4

想象一个表:如何组合SELECT语句以允许我计算SQL Server中的百分比,成功和失败?

CUST_PROMO(CUSTOMER_ID,促销),其被用作每一个客户收到促销之间的映射。

select promotion, count(customer_id) as promo_size 
from CUST_PROMO 
group by promotion 

这会让我们的客户总数在每个推广。现在

,我们已经得到了客户(CUSTOMER_ID,PROMO_RESPONDED,PROMO_PURCHASED),其中列出了在客户和推广得到了客户响应,并得到了他们购买。

select PROMO_RESPONDED, count(customer_id) as promo_responded 
from CUSTOMER 
group by PROMO_RESPONDED 

select PROMO_PURCHASED,count(customer_id) as promo_responded 
from CUSTOMER 
group by PROMO_PURCHASED 

这都是不言自明的;现在我已经掌握了每个促销成功的人数。

但是;我想最终是[以CSV格式]

PROMOTION,PROMO_SIZE,PROMO_RESPONDED,PROMO_PURCHASED,PROMO_RESPSUCCESSRATE,blah 

1,100,12,5,12%,... 
2,200,23,14,11.5%,... 

我不知道如何做到这一点。我可以联合上面的三个查询;但那实际上并不是我想要的。我想创建一个内存表,插入每个促销价值,然后做一个更新声明与一个联合反对它来设置每个值 - 但这很杂乱;并要求每个表/选择语句都有一个新的UPDATE语句。我也可以为每个结果集创建一个临时表,然后将它们结合在一起;但真的;谁想要这样做?

我想不出加入这个数据让任何意义的任何方式;因为我正在处理聚合。

所以,在最好的,我需要的是,像UNION,将结合的结果集的功能,反而会像相结合的列上的一个键,并添加这些列,而不是工会的它增加了行。描述使它听起来像一个JOIN;但我看不到那个工作。

感谢您的帮助!

回答

2
SELECT 
    cp.promotion, 
    PROMO_SIZE = COUNT(*), 
    PROMO_RESPONDED = COUNT(c1.customer_id), 
    PROMO_PURCHASED = COUNT(c2.customer_id), 
    PROMO_RESPSUCCESSRATE = COUNT(c1.customer_id) * 100.0/COUNT(*) 
FROM CUST_PROMO cp 
    LEFT JOIN CUSTOMER c1 
    ON cp.customer_id = c1.customer_id AND cp.promotion = c1.PROMO_RESPONDED 
    LEFT JOIN CUSTOMER c2 
    ON cp.customer_id = c2.customer_id AND cp.promotion = c2.PROMO_PURCHASED 
GROUP BY cp.promotion 
+0

这就是我最终这样做的结果;尽管所有解决方案都有优点。 – 2011-06-14 01:02:00

1

工作的呢?我不确定分割和乘法运算符,但是我相信我的逻辑是好的。关键是在select语句中使用相关的select子语句。

SELECT c.promotion, 
     COUNT(c.customer_id) as promo_size, 
     (SELECT COUNT(customer_id) 
      FROM CUSTOMER 
     WHERE PROMO_RESPONDED = c.promotion) PROMO_RESPONDED, 
     (SELECT COUNT(customer_id) 
      FROM CUSTOMER 
     WHERE PROMO_PURCHASED = c.promotion) PROMO_PURCHASED, 
     (SELECT COUNT(customer_id) *100/count(c.customer_id) 
     FROM CUSTOMER 
     WHERE PROMO_RESPONDED = c.promotion)              
FROM CUST_PROMO c 
GROUP BY c.promotion 

使用解码的清洁器的解决方案。仍不能确定的数学工作

select PROMOTION, count(CUSTOMER_ID) as promo_size, 
     SUM(DECODE(PROMO_RESPONDED, PROMOTION, 1, 0)) PROMO_RESPONDED, 
     SUM(DECODE(PROMO_PURCHASED, PROMOTION, 1, 0)) PROMO PURCHASED, 
     SUM(DECODE(PROMO_RESPONDED, PROMOTION, 1, 0))*100/count(CUSTOMER_ID) PROMO_RESPONDED 
from CUST_PROMO join CUSTOMER using CUSTOMER_ID 
group by PROMOTION 
+1

的可能的工作,但嵌套的选择应*总*避免如果连接可以用来代替。 – Colin 2011-06-04 01:34:28

+0

其实这可能会无法正常工作的promo_size将由集团,这将不是你的子查询之前发生后运行计算.. – Colin 2011-06-04 01:36:14

+0

这晚在这里,所以我不能告诉我们,如果你说这是错的,因为结果是incorect或一些'汇编'错误。但我我做错了 – marina 2011-06-04 01:44:13

1
WITH tmp AS 
(
    SELECT PROMOTION, 0 as promo_responded, 0 as promo_purchased, COUNT(customer_id) as total 
    FROM CUST_PROMO 
    GROUP BY PROMOTION 
    SELECT PROMOTION, COUNT(customer_id) as promo_responded, 0 as promo_purchased, 0 as total 
    FROM CUSTOMER 
    GROUP BY PROMO_RESPONDED 
    UNION 
    SELECT PROMOTION, COUNT(customer_id) as promo_purchased, 0 as promo_responded, 0 as total 
    FROM CUSTOMER 
    GROUP BY PROMO_PURCHASED 
) 
SELECT PROMOTION, SUM(promo_responded) as TotalResponded, SUM(promo_purchased) as TotalPurchased, SUM(Total) as TotalSize, 
     SUM(promo_responded)/SUM(Total) as ResponseRate, SUM(promo_purchased)/SUM(Total) as PurchaseRate 
FROM tmp 
1

是的,我认为JOIN荷兰国际集团三个集合查询是要走的路。 LEFT JOIN是为了防止某些促销没有回应或没有购买。

我也改变了COUNT(customer_id)COUNT(*)。其结果是一样的,除非customer_id域可以有两个表这最有可能是没有的情况下NULL值。但是,如果一个客户可能会出现在同一个促销代码表的两行,那么你应该改变那些为COUNT(DISTINCT customer_id)

SELECT prom.promotion 
    , prom.promo_size 
    , responded.promo_responded 
    , purchased.promo_purchased 
    , responded.promo_responded/prom.promo_size 
     AS promo_response_success_rate 
FROM 
    (SELECT promotion 
     , COUNT(*) AS promo_size 
     FROM CUST_PROMO 
     GROUP BY promotion 
    ) AS prom 
    LEFT JOIN 
    (SELECT PROMO_RESPONDED AS promotion 
      , COUNT(*) AS promo_responded 
     FROM CUSTOMER 
     GROUP BY PROMO_RESPONDED 
    ) AS responded 
    ON responded.promotion = prom.promotion 
    LEFT JOIN 
    (SELECT PROMO_PURCHASED AS promotion 
      , COUNT(*) AS promo_purchased 
     FROM CUSTOMER 
     GROUP BY PROMO_PURCHASED 
    ) AS purchased 
    ON purchased.promotion = prom.promotion