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
Логика:
- Получить встречу в вопросе
- Повторное присоединение к родительскому приложению
- Выбрать все результаты
Запрос:
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