SQL-запрос для поиска одной отсортированной записи - PullRequest
0 голосов
/ 09 июня 2009

Вот проблема, которую я пытаюсь решить. У меня есть таблица, в которой я храню StartExclusionDate и EndExclusionDate и устанавливаю ApplyDate для моего объекта (называемого исключением). В таблице может быть много записей ExtId.

Я хочу получить ApplyDate из последней непрерывной записи, в которой дата, переданная запросу, включена между StartExclusionDate и EndExclusionDate.

Итак, вот таблица, которую я создал в SQL 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 <= '15.06.2008', отсортировать ApplyDate DESC </li>
  • Если дата начала и окончания первой записи находятся между 15.06.2008, найдите запись, в которой изначально было установлено Исключение, проверив следующие записи

Я хотел найти способ сделать это без CURSOR, это возможно сделать с помощью запроса или 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

1 Ответ

2 голосов
/ 09 июня 2009
select top 1 * from table
where ApplyDate <= '4/15/2008'
and (startdate is null or startdate<= '4/15/2008')
and (enddate is null or enddate >= '4/15/2008')
and extid = '101'
order by  ApplyDate desc
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...