Получить значение Lead для нескольких разделов - PullRequest
0 голосов
/ 14 ноября 2018

У меня есть проблема, которую, я чувствую, можно решить с помощью разделов lag / lead +, но я не могу обойти ее.

Клиенты приглашаются участвовать в исследовательских проектах каждые два года (aprox.).Количество клиентов выбирается для каждого проекта.Некоторые клиенты отобраны для нескольких исследовательских проектов.Те получают приглашение.В некоторых случаях приглашение не отправляется.Если клиент не реагирует на приглашение, отправляется второе приглашение (напоминание).3-й, 4-й также возможны.

Мне нужно выяснить, было ли у клиента приглашение на предыдущий исследовательский проект.(И, опционально, какое приглашение было).

Набор данных выглядит следующим образом:

clientID | projectID | invitationID
  14     |    267    |     489
  14     |    267    |     325
  16     |    385    |     475
  17     |    546    |     NULL
  17     |    547    |     885
  17     |    548    |     901
  18     |    721    |     905
  18     |    834    |     906
  18     |    834    |     907
  19     |    856    |     908
  19     |    856    |     929
  19     |    857    |     931
  19     |    857    |     945
  19     |    858    |     NULL


Client 14 has had 2 invitations for the same research-project
Client 16 has had 1 invitation for 1 research-project
Client 17 has been selected for 3 research-projects but opted out for project 546, receiving 1 invitation each for the following projects. 
Client 18 has been selected for 2 research-projects. For the second project he got a 2 invitations.
Client 19 has been selected for three research-projects. For the first two a reminder was set. Client 19 was selected for project 858 but opted out thus no invitation.

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

clientID | projectID | invitationID | InvitedForPreviousProject
  14     |    267    |     489      |      0
  14     |    267    |     325      |      0
  16     |    385    |     475      |      0
  17     |    546    |     NULL     |      0
  17     |    547    |     885      |      0
  17     |    548    |     901      |      1 (885)
  18     |    721    |     905      |      0
  18     |    834    |     906      |      1 (905)
  18     |    834    |     907      |      1 (905)
  19     |    856    |     908      |      0
  19     |    856    |     929      |      0
  19     |    857    |     931      |      1 (908)
  19     |    857    |     945      |      1 (908)
  19     |    858    |     NULL     |      1 (931)

Можно ли это сделать с помощью LEAD, Rank, Dense-Rank?Создать заявление, включая данные ниже

declare @table table (
    [clientID] [int] NULL,
    [projectID] [int] NULL,
    [invitationID] [int] NULL
)
INSERT @table ([clientID], [projectID], [invitationID]) VALUES
(14, 267, 489),
(14, 267, 325),
(16, 385, 475),
(17, 546, NULL),
(17, 547, 885),
(17, 548, 901),
(18, 721, 905),
(18, 834, 906),
(18, 834, 907),
(19, 856, 908),
(19, 856, 929),
(19, 857, 931),
(19, 857, 945),
(19, 858, NULL)

Ответы [ 2 ]

0 голосов
/ 14 ноября 2018

Вам нужен столбец, который определяет порядок. Позвольте мне предположить, что есть дата приглашения, а также другие столбцы.

С этой информацией ваш флаг легко вычисляется путем сравнения двух значений:

  • минимальная дата приглашения для клиента
  • минимальная дата приглашения для клиента / id проекта

Когда они совпадают, это первый проект с приглашением.

Итак:

select t.*,
       (case when min(invitationDate) over (partition by clientId order by invitationDate) =
                  min(invitationDate) over (partition by clientId, projectId order by invitationDate)
             then 0 else 1                  
        end) as InvitedForPreviousProject
from @table t;
0 голосов
/ 14 ноября 2018

Может ли это помочь?

declare @table table (
    [clientID] [int] NULL,
    [projectID] [int] NULL,
    [invitationID] [int] NULL
)
INSERT @table ([clientID], [projectID], [invitationID]) VALUES
(14, 267, 489),
(14, 267, 325),
(16, 385, 475),
(17, 546, NULL),
(17, 547, 885),
(17, 548, 901),
(18, 721, 905),
(18, 834, 906),
(18, 834, 907),
(19, 856, 908),
(19, 856, 929),
(19, 857, 931),
(19, 857, 945),
(19, 858, NULL);

- в запросе используется DENSE_RANK() и коррелированный подзапрос

WITH ranked AS
(
    SELECT t.* 
         ,DENSE_RANK() OVER(PARTITION BY t.clientID ORDER BY t.projectID) AS InvRank
    FROM @table t
)
SELECT r.*
      ,earlierProject.invitationID
FROM ranked r
OUTER APPLY(SELECT TOP 1 *
            FROM ranked r2 
            WHERE r2.clientID=r.clientID
             AND  r2.projectID<r.projectID 
             AND  r2.InvRank=r.InvRank-1   
            ORDER BY invitationID ASC
            ) earlierProject
ORDER BY r.clientID,r.projectID,r.invitationID;

Аргумент приглашения будет иметь значение ПУСТО (NULL) в случае "0" в вашей таблице и будет установлен на нужное значение в случае обнаружения элемента.

Подсказка

Нет необходимости в APPLY на самом деле. Если вам нужен только invitationID, вы можете разместить подзапрос в виде столбца напрямую (немного быстрее). Но это лучше читать, и вы могли бы достать и другие столбцы ...

...