2016-02-16 1 views
-1

Мои извинения о дрянной титул, но я в полной потере, где начать с этим однимSQL запросов - комплекс, не слишком уверен, где начать

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

Для каждого клиента мы хотим, чтобы дата & описание их последнего связанного с назначением взаимодействия (независимо от того, отменено, запланировано или имеет), а также дату последнего пополнения рецепта, если оно существует

Table_1

User_ID  
------- 
    001 
    002 
    003 

Table_2

User_ID Date   Interaction 
------------------------------------------------------ 
    001  1/21/2015 Canceled Appointment 
    001  12/09/2014 Scheduled Appointment 
    001  12/01/2014 Called to Refill Prescription 
    002  2/1/2015 Had Appointment 
    002  12/2/2014 Called About Symptoms 
    002  11/18/2014 Scheduled Appointment 
    003  2/1/2015 Called to Refill Prescription 
    003  11/28/2014 Had Appointment 

Желаемая выход

User_ID Date   Appointment_Details  Prescription Refill Date 
------------------------------------------------------------------------ 
001  1/21/2015 Canceled Appointment  12/01/2014 
002  2/1/2015 Had Appointment   n/a 
003  11/28/2014 Had Appointment   2/1/2015 
+1

start pivot concept sql –

+2

Какой [tag: rdbms] вы используете? – Mureinik

+1

Добро пожаловать в StackOverflow: если вы отправляете код, XML или образцы данных **, пожалуйста ** выделите эти строки в текстовом редакторе и нажмите кнопку «образцы кода» ('{}') на панели инструментов редактора, чтобы получить хороший формат и синтаксис выделить его! –

ответ

2

Лучше решить это в три этапа:

Для каждого User_ID выберите последнюю запись, в которой находится взаимодействие в списке «Отмененное назначение», «Назначение по расписанию» или «Назначение». Для этого мы можем использовать Коррелированный подзапрос, чтобы найти max (date) для каждого user_id, где взаимодействие находится в этом списке.

SELECT 
    user_id, 
    DATE, 
    interaction 
FROM table_2 t2 
WHERE DATE IN (
     SELECT max(DATE) 
     FROM table_2 
     WHERE t2.user_id = user_id 
      AND Interaction IN (
       'Cancelled Appointment', 
       'Scheduled Appointment', 
       'Had Appointment' 
       ) 
     ) 

Для каждого User_ID выберите запись, в которой взаимодействует «Called to refill Prescription». Это немного просто, так как нужно только фильтровать для «Called to refill prescription».

SELECT user_id, date FROM table_2 WHERE Interaction = 'Called To Refill Prescription' 

Теперь мы просто присоединиться к ним вместе, используя LEFT OUTER JOIN, поэтому мы выбираем все записи из первых набора записей, а только те, которые соответствие со второй записи установить

SELECT 
    t1.user_id, 
    t1.date 
    t1.Interaction as Appointment_Details 
    t2.date as Prescription_Refill_Date 
FROM 
    (
     SELECT 
      user_id, 
      DATE, 
      interaction 
     FROM table_2 t2 
     WHERE DATE IN (
       SELECT max(DATE) 
       FROM table_2 
       WHERE t2.user_id = user_id 
        AND Interaction IN (
         'Cancelled Appointment', 
         'Scheduled Appointment', 
         'Had Appointment' 
         ) 
       ) 
    ) t1 
    LEFT OUTER JOIN (SELECT user_id, date FROM table_2 WHERE Interaction = 'Called To Refill Prescription') t3 
     ON t1.user_id = t3.user_id 

Большой нюанс здесь заключается в том, что он действительно работает только в том случае, если user_id отображается с полным набором (серия запланированных/отмененных/назначенных встреч и сингл «Called to refill Prescription»). Вещи будут немного более беспорядочными, если необходимо показать user_id через несколько посещений и несколько рецептурных заправок. Кроме того, если запланированный и отмененный или запланированный и назначенный на ту же дату, вы получите дубликаты. Это объясняется тем, что нет логики, в которой говорится, что последнее произошло. В любом случае, это должно привести вас в стадион.

+0

В LEFT OUTER JOIN вам нужно выбрать max (date). Я все еще думаю, как избежать дубликатов в основном запросе. –

+0

Было бы неплохо убедиться, что был учтен только последний набор взаимодействий. Если лицо не запросило пополнение, то через год у него была назначена встреча, и в этом случае вы, вероятно, не захотели бы связанных с взаимодействием. Я сделал аналогичную логику, где есть жизненный цикл для набора взаимодействий, затем проходит период, затем начинается новый жизненный цикл, но он был в Teradata, где логика PERIOD и функции Window упрощают вещи. – JNevill

+0

Hi Невилл, см. Мой полный ответ ниже. Я дам вам кредит, хотя для начала тоже. Yo ur последний комментарий тоже можно было бы сделать, добавив в левое внешнее соединение условие where, где вы указываете, что max (date) должен быть больше текущей даты - 1 год. –

1

Это должно сделать это, если вы используете SQL Server:

Создание выборки данных:

CREATE TABLE #Temp1 ([User_ID] VARCHAR(5)) 
INSERT INTO #Temp1 
VALUES('001'),('002'),('003') 

CREATE TABLE #Temp2 ([User_ID] VARCHAR(5),[Date] DATE, Interaction VARCHAR(50)) 
INSERT INTO #Temp2 
VALUES('001','1/21/2015','Canceled Appointment'), 

('001','12/09/2014','Scheduled Appointment'), 

('001','12/01/2014','Called to Refill Prescription'), 

('002','2/1/2015','Had Appointment'), 

('002','12/2/2014','Called About Symptoms'), 

('002','11/18/2014','Scheduled Appointment'), 

('003','2/1/2015','Called to Refill Prescription'), 

('003','11/28/2014','Had Appointment') 

запрос с использованием PIVOT:

SELECT [User_ID], 
     COALESCE([Had Appointment], [Canceled Appointment]) AS [Date], 
     CASE WHEN [Had Appointment] IS NULL AND [Canceled Appointment] IS NOT NULL THEN 'Canceled Appointment' 
      WHEN [Had Appointment] IS NOT NULL AND [Canceled Appointment] IS NULL THEN 'Had Appointment ' 
     END AS [Appointment_Details], 
     [Called to Refill Prescription] 
FROM 
( SELECT * 
    FROM #Temp2 AS B) p 
PIVOT 
( MIN([Date]) 
    FOR [Interaction] IN ( [Had Appointment],[Canceled Appointment], 
     [Scheduled Appointment], 
     [Called to Refill Prescription] ) 
) AS pvt 

Результат:

enter image description here

Если вы хотите, формат даты, чтобы показать, как США формат дд/мм/гггг, то вы можете конвертировать их в VARCHAR CONVERT(VARCHAR(10),<your column name>,1):

SELECT [User_ID], 
     CONVERT(VARCHAR(10),COALESCE([Had Appointment], [Canceled Appointment]),1) AS [Date], 
     CASE WHEN [Had Appointment] IS NULL AND [Canceled Appointment] IS NOT NULL THEN 'Canceled Appointment' 
      WHEN [Had Appointment] IS NOT NULL AND [Canceled Appointment] IS NULL THEN 'Had Appointment ' 
     END AS [Appointment_Details], 
     CONVERT(VARCHAR(10),[Called to Refill Prescription],1) AS [Called to Refill Prescription] 
FROM 
( SELECT * 
    FROM #Temp2 AS B) p 
PIVOT 
( MIN([Date]) 
    FOR [Interaction] IN ( [Had Appointment],[Canceled Appointment], 
     [Scheduled Appointment], 
     [Called to Refill Prescription] ) 
) AS pvt 

Результаты:

enter image description here

0
SELECT 
    t1.user_id, 
    t1.date 
    t1.Interaction as Appointment_Details 
    t2.date as Prescription_Refill_Date 
FROM 
    (
     SELECT 
      user_id, 
      DATE, 
      interaction 
     FROM table_2 t2 
     WHERE DATE IN (
       SELECT max(DATE) 
       FROM table_2 
       WHERE t2.user_id = user_id 
        AND Interaction IN (
         'Cancelled Appointment', 
         'Scheduled Appointment', 
         'Had Appointment' 
         ) 
       ) 
      AND Interaction IN (
       SELECT max(Interaction) 
       FROM table_2 
       WHERE t2.user_id = user_id 
        AND Interaction IN (
         'Cancelled Appointment', 
         'Scheduled Appointment', 
         'Had Appointment' 
         ) 
        AND DATE = t2.date 
       )  
    ) t1 
    LEFT OUTER JOIN (SELECT max(date) FROM table_2 
         WHERE Interaction = 'Called To Refill Prescription') t3 
      ON t1.user_id = t3.user_id 

Это это ответ от Nevill, в том числе избежание дубликатов. Вы можете выбрать максимальное (взаимодействие) или мин (взаимодействие), так как вы предпочитаете порядок, в котором будет отображаться «Отменена», «Засчитано» или «Запланированная встреча». Единственное, что вы не можете получить, если бы все три были в ту же дату.

Несомненно, это может быть сделано с помощью оператора CASE, но это делает запрос еще более сложным.

+0

Как предложил Nevill, LEFT OUTER JOIN можно было бы изменить на ... LEFT OUTER JOIN (SELECT max (date) FROM table_2 WHERE Взаимодействие = 'Called To Refill Prescription' и max (date)> текущая дата - 1 год) t3 ON t1.user_id = t3.user_id –

0
SELECT t.[User_ID], 
     t.[Date], 
     t.[Interaction] [Appointment_Details], 
     p.[Prescription Refill Date] 
FROM (SELECT Table_2.*, 
       ROW_NUMBER() OVER (PARTITION BY Table_1.[User_ID] ORDER BY Table_2.[Date] DESC) Rn 
     FROM Table_1 
       JOIN Table_2 ON Table_1.[User_ID] = Table_2.[User_ID] 
     WHERE [Interaction] IN ('Canceled Appointment', 'Scheduled Appointment', 'Had Appointment') 
     ) t 
     OUTER APPLY (SELECT MAX([Date]) [Prescription Refill Date] 
        FROM Table_2 
        WHERE t.[User_ID] = Table_2.[User_ID] 
          AND [Interaction] = 'Called to Refill Prescription' 
        ) p 
WHERE t.Rn = 1 
Смежные вопросы