SQL Server Рекурсивный запрос

Несколько дней назад я задал вопрос о SO относительно помощи по рекурсивному запросу.

Проблема этого вопроса была "Как получить историю назначений человека".

Теперь у меня есть проблема, похожая на эту, но она должна ответить на немного другой вопрос:

How to get an Appointment history?

Например, если встреча с ID = 5 была отложена один раз и была отложена на другую встречу, как мне получить следующий результат?

AppointmentID         PrevAppointmentID
-----------------    ----------------------
1                     NULL
5                     1
12                    5

Спасибо за помощь

Обновление:

Эти скрипты помогут создать таблицу для ваших испытаний.

CREATE TABLE [dbo].[Appointments](
    [AppointmentID] [int] IDENTITY(1,1) NOT NULL,
    [IssueID] [int] NOT NULL,
    [Location] [varchar](255) NOT NULL,
    [Description] [varchar](255) NOT NULL,
    [AppointmentDate] [datetime] NOT NULL,
    [AppointmentHour] [datetime] NOT NULL,
    [Done] [bit] NOT NULL,
    [PrevAppointmentID] [int] NULL,
 CONSTRAINT [PK_Appointments] PRIMARY KEY CLUSTERED 
(
    [AppointmentID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

3 ответа

Решение

Я не хотел полностью угнать его ответ, поэтому:

Используя ответ Брэда

Вот запрос, чтобы получить полную историю:

WITH    cte
          AS ( SELECT   AppointmentId ,
                        PrevAppointmentId
               FROM     Appointments
               WHERE    AppointmentId = @AppointmentId
               UNION ALL
               SELECT   prev.AppointmentId ,
                        prev.PrevAppointmentId
               FROM     Appointments prev
                        INNER JOIN cte curr ON prev.AppointmentId = curr.PrevAppointmentId
             ),
        cte1
          AS ( SELECT   AppointmentId ,
                        PrevAppointmentId
               FROM     Appointments
               WHERE    AppointmentId = @AppointmentId
               UNION ALL
               SELECT   prev.AppointmentId ,
                        prev.PrevAppointmentId
               FROM     Appointments prev
                        INNER JOIN cte1 curr ON prev.PrevAppointmentId = curr.AppointmentId
             )
    SELECT  *
    FROM    cte
    UNION
    SELECT  *
    FROM    cte1

Логика:

  1. Получить встречу в вопросе
  2. Повторное присоединение к родительскому приложению
  3. Выбрать все результаты

Запрос:

DECLARE @appointmentId INT
SET @appointmentId = 3

--
;
WITH  past
      AS ( SELECT   AppointmentId ,
                    PrevAppointmentId
           FROM     Appointments
           WHERE    AppointmentId = @AppointmentId
           UNION ALL
           SELECT   prev.AppointmentId ,
                    prev.PrevAppointmentId
           FROM     Appointments prev
                    INNER JOIN cte curr ON prev.AppointmentId = curr.PrevAppointmentId
         ),
    future
      AS ( SELECT   AppointmentId ,
                    PrevAppointmentId
           FROM     Appointments
           WHERE    AppointmentId = @AppointmentId
           UNION ALL
           SELECT   prev.AppointmentId ,
                    prev.PrevAppointmentId
           FROM     Appointments prev
                    INNER JOIN cte1 curr ON prev.PrevAppointmentId = curr.AppointmentId
         )
SELECT  *
FROM    past OPTION(MAXRECURSION 500)
UNION
SELECT  *
FROM    future OPTION(MAXRECURSION 500)

В ответ на вопрос от ОП:

Эффективные знакомства

Эффективное знакомство - это когда вы добавляете DateTime столбец таблицы, который контролирует, когда запись становится "эффективной". Затем столбец добавляется к PK таблицы, в которой каждая запись представляет собой запись того, что было "в силе" в данный момент времени (дата вступления в силу). С эффективным знакомств вы никогда не DELETE или же UPDATE, только INSERT Это означает, что у вас всегда есть полная история объекта с течением времени.

Чтобы найти наиболее эффективную запись, вы выбираете строку с максимальной эффективностью, которой нет в будущем.

SELECT *
FROM   Appointments a1
WHERE  EffectiveDate = (SELECT MAX(EffectiveDate)
                        FROM   Appointments a2
                        WHERE  a1.AppointmentId = a2.AppointmentId
                               AND a2.EffectiveDate <= ISNULL(@asOfDate, GETDATE()
                       )

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

Таким образом, чтобы найти историю встречи, вы просто:

SELECT *
FROM   Appointments
WHERE  AppointmentId = @appointmentId
ORDER BY EffectiveDate
Другие вопросы по тегам