【问题标题】:Horizontal DISTINCT COUNT in SQL Server or a COUNT IF without counting duplicatesSQL Server 中的水平 DISTINCT COUNT 或不计算重复项的 COUNT IF
【发布时间】:2011-06-19 09:34:46
【问题描述】:

我已经过度简化了以下示例,但请注意,我确实需要我所描述的结果。

我有一个表格,其中包含有关客户的信息,包括他们是如何被推荐的。 例如MyTable(编辑:我的过度简化导致答案不起作用。它们是很好的答案,但不能解决我的问题。为了清楚起见,我添加了最后一块拼图):

STORE    CUS_ID REFERRED    MONEYMADE  
 1        11        RADIO         10.00
 1        15        WALKIN        20.00
 1        11        RADIO         30.00
 2        12        RADIO         40.00
 2        12        RADIO         50.00
 3        13        WALKIN        60.00
 3        14        WALKIN        70.00

我想统计按特定类型推荐的 DISTINCT 客户的数量,并按商店对他们进行分组。我可以做到以下几点:

SELECT 
   STORE, COUNT(DISTINCT CUS_ID) AS COUNTEM, 
   REFERRED, SUM(MONEYMADE) 
FROM MyTable 
GROUP BY REFERRED, STORE

这给出了以下结果:

STORE    COUNTEM    REFERRED    MONEYMADE
 1        1         RADIO        40.00
 1        1         WALKIN       20.00
 2        1         RADIO        90.00
 3        2         WALKIN       130.00

但是,我真的需要这样的结果:

STORE    RADIO  RADIO_MONEY   WALKIN   WALKIN_MONEY
 1        1      40.00         1         20.00
 2        1      90.00         0         0.00
 3        0      0.00          2         130.00

我尝试使用 SUM 和 CASE 进行查询,但它计算了重复项。例如:

SELECT 
   STORE, 
   SUM (CASE REFERRED WHEN 'RADIO' THEN 1 ELSE 0 END) AS RADIO,  
   SUM (CASE REFERRED WHEN 'RADIO' THEN MONEYMADE ELSE 0 END) AS RADIO_MONEY,  
   SUM (CASE REFERRED WHEN 'WALKIN' THEN 1 ELSE 0 END) AS WALKIN
   SUM (CASE REFERRED WHEN 'WALKIN' THEN MONEYMADE ELSE 0 END) AS WALKIN_MONEY, 
FROM MyTable
GROUP BY STORE

返回这个不正确的结果:

STORE    RADIO  RADIO_MONEY   WALKIN   WALKIN_MONEY
 1        2      40.00         1         20.00
 2        2      90.00         0         0.00
 3        0      0.00          2         130.00

有没有办法解决这个问题?我已经搜索了“count if”类型的函数,但我唯一找到的是 sum - case 方法。

【问题讨论】:

    标签: sql sql-server sql-server-2005 tsql pivot


    【解决方案1】:

    EDIT 因为您需要对另一个字段求​​和。你应该在 SUM/CASE 之前做总和

    自带样本数据

    --TEST DATA
    DECLARE @MyTable table 
    (STORE int,  CUST_ID int , Referred varchar(6) ,MONEYMADE   Money )
    
    INSERT INTO @MyTable VALUES  
    (1,        11,        'RADIO' ,        10.00)
    INSERT INTO @MyTable VALUES  
    (1,        15,        'WALKIN',        20.00)
    INSERT INTO @MyTable VALUES 
    (1,        11,        'RADIO' ,       30.00)
    INSERT INTO @MyTable VALUES 
    (2,        12,        'RADIO' ,        40.00)
    INSERT INTO @MyTable VALUES 
    (2,        12,        'RADIO' ,       50.00)
    INSERT INTO @MyTable VALUES 
    (3,        13,        'WALKIN',        60.00)
    INSERT INTO @MyTable VALUES 
    (3,        14,        'WALKIN',        70.00)
    

    --使用枢轴

      SELECT 
        pk.STORE,
        pk.RADIO,
        pk.WALKIN,
        ISNULL(pv.RADIO,0) as RADIO_MONEY,
        ISNULL(pv.WALKIN,0)as WALKIN_MONEY
    
     FROM
     (SELECT  STORE,   
              REFERRED ,
              MONEYMADE   
      FROM  @MyTable) p
              PIVOT (SUM(MONEYMADE) FOR REFERRED in (WALKIN, RADIO)) as  pv
      INNER JOIN         
     ( SELECT  DISTINCT STORE,   
                        REFERRED ,
                        CUST_ID   
       FROM  @MyTable) p
                PIVOT ( COUNT (CUST_ID) FOR REFERRED in (WALKIN, RADIO)) as  pk
      ON pv.store = pk.STORE
    

    --不使用 PIVOT

    SELECT 
       STORE,
       SUM(CASE REFERRED WHEN  'RADIO' THEN 1 ELSE 0 END )AS RADIO,
       SUM(CASE REFERRED WHEN 'WALKIN' THEN 1 ELSE 0 END )AS WALKIN,
       SUM(CASE REFERRED WHEN  'RADIO' THEN MONEYMADE ELSE 0 END )AS RADIO_MONEYMADE,
       SUM(CASE REFERRED WHEN 'WALKIN' THEN MONEYMADE ELSE 0 END )AS WALKIN_MONEYMADE
    FROM   
       (
    
    SELECT  
        STORE,   
        CUST_ID, 
        REFERRED ,
        SUM(MONEYMADE )MONEYMADE
      FROM 
        @MyTable p
      GROUP BY 
      STORE,
      REFERRED,
      CUST_ID
    
    
    ) t
    group by store
    

    两种技术的输出

        STORE       RADIO       WALKIN      RADIO_MONEY           WALKIN_MONEY
        ----------- ----------- ----------- --------------------- ---------------------
        1           1           1           40.00                 20.00
        2           1           0           90.00                 0.00
        3           0           2           0.00                  130.00
    

    【讨论】:

    • 对不起,我应该提到还有一些列阻止了它的工作。换句话说,那些其他列使行独一无二。我将编辑我的原始帖子。不过,这是一个很好的建议,我很感激。
    • @LittleTreeX。编辑没有帮助。三列上的 DISTINCT 删除了重复。那么当你做 SUM/CASE 应该没问题
    • 我再次编辑了我的问题,以便(希望)更清楚地说明我的问题,以及为什么我认为这个解决方案不起作用。我想说这个答案确实回答了我最初写的问题(抱歉造成混淆,但感谢您的帮助)。
    • @LittleTreeX 好的,我已经更新了我的答案以包括赚钱字段
    • PIVOT 对我不起作用,原因是:“PIVOT”附近的语法不正确。您可能需要将当前数据库的兼容级别设置为更高的值才能启用此功能。任何想法如何解决这个问题?
    【解决方案2】:

    轮换 SQL 结果至少很棘手。如果您想直接从查询中呈现数据,您可能不得不牺牲查询的灵活性并硬编码大量信息(如列名及其计数)。

    所以我想建议的是在实际使用查询的后端做更多的事情。如果可以接受并且您可以自己轮换结果,那么您可以执行以下操作:

    ;with R(Referred) as (
      select distinct REFERRED from MyTable
    )
    select t.STORE, COUNT(*) as COUNT, t.REFERRED
    from MyTable t
      left join R on r.REFERRED = t.REFERRED
    group by t.STORE, t.REFERRED
    

    【讨论】:

      【解决方案3】:

      我认为,您的脚本已修改为符合您想要实现的目标:

      SELECT 
         STORE, 
         COUNT(DISTINCT CASE REFERRED WHEN 'RADIO' THEN CUS_ID END) AS RADIO,  
         SUM  (CASE REFERRED WHEN 'RADIO' THEN MONEYMADE ELSE 0 END) AS RADIO_MONEY,  
         COUNT(DISTINCT CASE REFERRED WHEN 'WALKIN' THEN CUS_ID END) AS WALKIN
         SUM  (CASE REFERRED WHEN 'WALKIN' THEN MONEYMADE ELSE 0 END) AS WALKIN_MONEY, 
      FROM MyTable
      GROUP BY STORE
      

      【讨论】:

        猜你喜欢
        • 2016-01-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-10
        • 2021-09-15
        • 2016-02-19
        • 2011-10-30
        相关资源
        最近更新 更多