Горизонтальный DISTINCT COUNT в SQL Server или COUNT IF, без учета дубликатов - PullRequest
1 голос
/ 01 февраля 2011

Я упростил приведенные ниже примеры, однако, пожалуйста, знайте, что мне действительно нужны результаты, которые я описываю.

У меня есть таблица, которая содержит информацию о клиентах, включая то, как они были направлены. Например, 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», но единственное, что я нашел, - это метод суммирования.

Ответы [ 3 ]

4 голосов
/ 01 февраля 2011

РЕДАКТИРОВАТЬ Так как вам нужно СУММИТЬ другое поле.Вы должны сделать сумму до 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)

- USING PIVOT

  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
0 голосов
/ 01 февраля 2011

Вот ваш сценарий, измененный, чтобы соответствовать, я думаю, тому, чего вы пытаетесь достичь:

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
0 голосов
/ 01 февраля 2011

Ротация 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...