Вот проблема, которую я пытаюсь решить. У меня есть таблица, где я храню StartExclusionDate и EndExclusionDate и устанавливаю ApplyDate для моего объекта (это называется Исключение). В таблице может быть много записей ExtId.SQL-запрос поможет найти одиночную, отсортированную запись
Я хочу получить ApplyDate из последней непрерывной записи, где дата, переданная запросу, включена между StartExclusionDate и EndExclusionDate.
Так вот таблица я создал в SQL Server 2005:
Id int PK
ExtId int FK
StartExclusionDate datetime null
EndExclusionDate datetime null
ApplyDate not null
А вот пример набора данных:
ID | ExtID | StartDate | EndDate | ApplyDate
--------------------------------------------------------
1 101 11/15/2005 3/15/2010 11/15/2005
2 101 12/30/2005
3 101 1/1/2000 1/1/2000 1/1/2006
4 101 4/1/2008 4/1/2008
5 101 8/1/2010 6/1/2008
6 101 11/1/2006 12/31/2010 11/1/2009
Я проходил мимо 2 параметра, @ExtId и @dtDate. Запись, которую я хочу получить на основе следующих условий: @ExtId = 101, @dtDate = '6/15/2008'
будет ID = 4
Логика такова:
- Получить все записи для ExtId = 101 и где ApplyDate < = «6/15/2008' , сортировать ApplyDate DESC
- Если первая запись в дату начала и окончания находятся между „6/15/2008“, найти запись, где исключение первоначально был установлен путем проверки на следующий записей
Я хотел найти способ сделать это без C URSOR, можно ли сделать запрос или CTE?
EDIT: Вот это делается с курсором
IF OBJECT_ID('TempDB..#t_edr','U') IS NOT NULL
DROP TABLE #t_edr
CREATE TABLE #t_edr
(
Id INT NOT NULL,
ExtId INT NOT NULL,
StartDate DATETIME NULL,
EndDate DATETIME NULL,
ApplyDate DATETIME NOT NULL
)
DECLARE @ExtID INT, @dtDate DATETIME, @dtReturn DATETIME
SELECT @ExtID = 101, @dtDate = '6/15/2008'
SET NOCOUNT ON
INSERT INTO #t_edr VALUES (1, 101, '11/15/2005', '3/15/2010', '11/15/2005')
INSERT INTO #t_edr VALUES (2, 101, NULL, NULL, '12/30/2005')
INSERT INTO #t_edr VALUES (3, 101, '1/1/2000', '1/1/2000', '1/1/2006')
INSERT INTO #t_edr VALUES (4, 101, '4/1/2008', NULL, '4/1/2008')
INSERT INTO #t_edr VALUES (5, 101, NULL, '8/1/2010', '6/1/2008')
INSERT INTO #t_edr VALUES (6, 101, '11/1/2006', '12/31/2010', '6/1/2009')
SET NOCOUNT OFF
IF EXISTS (
SELECT EDR.ID FROM #t_edr EDR
INNER JOIN (SELECT TOP 1 ID FROM #t_edr WHERE ExtId = @ExtID AND ApplyDate <= @dtDate ORDER BY ApplyDate DESC) LatestEDR
ON EDR.ID = LatestEDR.ID
WHERE ExtId = @ExtID
AND ApplyDate <= @dtDate
AND (StartDate IS NULL OR StartDate <= @dtDate)
AND (EndDate IS NULL OR EndDate >= @dtDate)
)
BEGIN
DECLARE @ID INT, @StartEDR DATETIME, @EndEDR DATETIME, @ApplyDate DATETIME,
@CurrentApplyDate DATETIME, @Continue BIT
DECLARE c CURSOR LOCAL FAST_FORWARD FOR
SELECT Id, StartDate, EndDate, ApplyDate FROM #t_edr
WHERE ExtId = @ExtID AND ApplyDate <= @dtDate ORDER BY ApplyDate DESC
OPEN c
FETCH NEXT FROM c INTO @id, @startedr, @endedr, @ApplyDate
IF @@FETCH_STATUS <> 0 SET @Continue = 0
ELSE SET @Continue = 1
SET @CurrentApplyDate = @ApplyDate
WHILE @Continue = 1
BEGIN
IF @StartEDR >= @dtDate OR @EndEDR <= @dtDate
SET @Continue = 0
IF @Continue = 1
BEGIN
SET @CurrentApplyDate = @ApplyDate
FETCH NEXT FROM c INTO @id, @startedr, @endedr, @ApplyDate
IF @@FETCH_STATUS <> 0 SET @Continue = 0
END
END
CLOSE c
DEALLOCATE c
SELECT @CurrentApplyDate
END
ELSE
PRINT 'NOT EXCLUDED'
DROP TABLE #t_edr
Это будет возвращать первую запись (ID = 1), так как он соответствует StartDate и критерии EndDate –
Вы правы, порядок должен опускаться. Проверьте это сейчас – tekBlues
Этот запрос возвращает ID = 4. Я неправильно установил дату, которую нужно передать. Это должно быть «6/15/2008» вместо «4/15/2008» = ( Я обновил пример, извините за путаницу - уже был длинный день –