SQL Server Рекурсивный запрос - PullRequest
3 голосов
/ 25 октября 2010

Несколько дней назад я задал вопрос о 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 ]

3 голосов
/ 25 октября 2010

Логика:

  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)
3 голосов
/ 25 октября 2010

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

Использование ответа Брэда

Вот запрос для получения полной истории:

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
2 голосов
/ 25 октября 2010

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

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

Эффективное датирование - это когда вы добавляете в таблицу столбец 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
...