Как рассчитать пропавших клиентов - PullRequest
0 голосов
/ 01 июля 2018

Как рассчитать недостающие записи клиентов за предыдущий год. Пример ввода 2008 имеет идентификатор клиента ( 1,2,3,4,5,6 ), но в 2009 году есть только идентификатор клиента ( 2 и 3 ), поэтому общее значение отсутствует идентификатор клиента ( 1,4,5,6 ) желаемые выходные данные содержат это общее число 4 в 2009 . То же самое для 2007 и 2008. Нужен запрос для желаемого результата.

Структура таблицы :

CREATE TABLE [dbo].[tblProductClient](
    [Year] [nchar](10) NULL,
    [Product] [nchar](10) NULL,
    [Client] [nchar](10) NULL,
    [TotalMissingClient] [int] NULL
) ON [PRIMARY]

Пример таблицы данных

Year    Product Client  TotalMissingClient
2008        A    1          NULL
2008        A    2          NULL
2008        A    3          NULL
2007        B    3          NULL
2007        B    2          NULL
2008        B    1          NULL
2007        A    2          NULL
2009        A    2          NULL
2009        A    3          NULL
2008        A    4          NULL
2008        A    5          NULL
2008        A    6          NULL

Требуемый выход

Year    Product Client  TotalMissingClient
2008        A      1            0
2008        A      2            0
2008        A      3            0
2007        B      3            NULL
2007        B      2            NULL
2008        B      1            NULL
2007        A      2            NULL
2009        A      2            4
2009        A      3            4
2008        A      4            0
2008        A      5            0
2008        A      6            0

Ответы [ 2 ]

0 голосов
/ 01 июля 2018

Ваш желаемый результат содержит только те комбинации года / продукта, которые содержатся в базовой таблице. Это означает, что если все клиенты предыдущего года будут отсутствовать, вы не увидите этого. Пример: продукт B имел 1 покупателя в 2008 году, но не имел покупателя в 2009 году. Кроме того, у продукта B было 2 клиента в 2007 году и 1 (другой, такой новый) клиент в 2008 году. Ваш желаемый результат показывает NULL в этом случае, но не должен ли он показать 2 отсутствующих клиента (и 1 нового клиента)? Цифры, похоже, зависят только от года и продукта. Я думаю, что было бы более полезно увидеть всю дельту между предыдущим и текущим годом, то есть количество клиентов, пропавших клиентов и новых клиентов. Это, конечно, будет работать, только если не будет пропущенных лет. Чтобы скрыть дельту между последним записанным годом и следующим годом, я использовал функцию RANK:

WITH
  compare ([Year], Product, ThisYearClient, PrevYearClient, LoyalClient) AS (
    SELECT ISNULL(this.[Year],  prev.[Year]+1)
      , ISNULL(this.Product, prev.Product)
      , this.Client, prev.Client
      , CASE WHEN this.Client = prev.Client THEN this.Client ELSE NULL END
    FROM tblProductClient this
      FULL JOIN tblProductClient prev
        ON this.Product = prev.Product 
        AND this.Client = prev.Client 
        AND this.[Year] = prev.[Year]+1
  ),
  totals ([Year], Product, ClientsThisYear, ClientsPrevYear, LoyalClients, R) AS (
    SELECT [Year], Product
      , COUNT(ThisYearClient)
      , COUNT(PrevYearClient)
      , COUNT(LoyalClient)
      , RANK() OVER (ORDER BY [Year] DESC)
    FROM compare
    GROUP BY [Year], Product
  )
SELECT [Year], Product, ClientsThisYear, ClientsPrevYear, LoyalClients 
  , ClientsThisYear - LoyalClients AS NewClients
  , ClientsPrevYear - LoyalClients AS MissingClients
FROM totals WHERE R > 1
ORDER BY [Year], Product
0 голосов
/ 01 июля 2018

Я думаю, что это то, что вы хотите, захвачено:

select t.*,
       (count(distinct client) over () -
        count(distinct clinet) over (partition by year)
       ) as TotalMissingClient
from t;

Увы, SQL Server не поддерживает count(distinct) с оконными функциями. Итак, один из методов - использовать вложенные оконные функции:

select t.*,
       (max(rank_c) over () -
        max(rank_yc) over (partition by year)
       ) as TotalMissingClient
from (select t.*,
             dense_rank() over (order by client) as rank_c,
             dense_rank() over (partition by year order by client) as rank_yc
      from t
     ) t;

EDIT:

Мне кажется, я неправильно понял вопрос. Вышеуказанное решает проблему для всех клиентов за все годы. Вы просто хотите один год по сравнению с предыдущим:

select t.*, tprev.TotalMissingClient
from t left join
     (select tprev.year, count(distinct tt.client) as TotalMissingClient
      from t tprev left join
           t tt
           on tprev.year = tt.year - 1
              tprev.client = tt.client
      where tt.client is null
      group by tprev.year
     ) tprev
     on tprev.year = t.year - 1;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...