Как получить все строки из таблицы календаря, используя набор результатов в качестве входных данных - PullRequest
0 голосов
/ 22 января 2019

Мне нужно найти все даты между 2 датами из набора результатов.
В моей базе данных есть таблица календаря, которая содержит одну строку для каждой даты от нескольких лет назад до достаточно дальнего будущего.

Теперь у меня есть этот запрос

select convert(date, r.LaadDatum), 
       convert(date, r.LosDatum)
from   tblPlanning p
  inner join tblRit r on p.RitID = r.RitID 
where  r.ChauffeurID = 201
and    (convert(date, r.LaadDatum) >= '20180812' and convert(date, r.LaadDatum) <= '20180921')
and    datediff(day, r.LaadDatum, r.LosDatum) > 1

и возвращает этот набор результатов

COLUMN1     COLUMN2 
-------     ------- 
2018-08-14  2018-08-16  
2018-08-20  2018-08-22  
2018-09-01  2018-09-03  
2018-09-08  2018-09-10  
2018-09-14  2018-09-17  

Используя этот набор результатов в качестве входных данных, мне нужен следующий результат:

2018-08-15  
2018-08-21  
2018-09-02  
2018-09-09  
2018-09-15  
2018-09-16  

Другими словами, все строки таблицы календаря, которые находятся между датами из запроса выше. Таблица календаря называется tblCalendar.
Как это можно сделать?
Возможно, очень просто, но по какой-то причине я просто не вижу этого

Ответы [ 3 ]

0 голосов
/ 22 января 2019

Посмотрите на это.

DECLARE @myTable AS TABLE (Column1 DATE, Column2 DATE);

INSERT INTO @myTable (Column1, Column2)
VALUES ('2018-08-14', '2018-08-16')
,      ('2018-08-20', '2018-08-22')
,      ('2018-09-01', '2018-09-03')
,      ('2018-09-08', '2018-09-10')
,      ('2018-09-14', '2018-09-17');

WITH cte AS
    (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) RN
       FROM master..spt_values)
SELECT          DATEADD(DAY,rn,Column1) DayToShow
  FROM          @myTable
 CROSS APPLY    cte
 WHERE DATEADD(DAY,rn,Column1) < column2

Вы должны найти его быстрее, чем итеративный метод cte, однако он ограничен диапазонами дат около 2500 дней.Вы можете использовать кросспайлы внутри cte, чтобы получить больше строк, если хотите.

0 голосов
/ 22 января 2019

Я бы использовал курсор здесь.это как для каждого.пожалуйста, попробуйте этот код.вывод @TempTable, который содержит все между датами

Declare @TempTable table (BetweenDate datetime)
Declare @FromDate datetime, 
        @ToDate datetime,
        @date datetime

Declare DatesCursor Cursor For
        Select FromDate, ToDate From (
                     select convert(date, r.LaadDatum) FromDate, 
                            convert(date, r.LosDatum) ToDate 
                     from   tblPlanning p
                        inner join tblRit r on p.RitID = r.RitID 
                     where  r.ChauffeurID = 201
                         and    (convert(date, r.LaadDatum) >= '20180812' 
                         and convert(date, r.LaadDatum) <= '20180921')
                         and    datediff(day, r.LaadDatum, r.LosDatum) > 1) t


    Open DatesCursor
    Fetch Next From DatesCursor Into @FromDate,  @ToDate

    While @@Fetch_Status = 0
    Begin
        If (@FromDate is not null and @ToDate is not null )
            Begin
                SET @date = DATEADD(day, 1, @FromDate) 
                WHILE (@date < @ToDate)
                BEGIN
                    insert @TempTable Values(@date)
                    SET @date = DATEADD(day, 1, @date) 
                END
        END
        Fetch Next From DatesCursor Into @FromDate,  @ToDate
    End

    Close DatesCursor

    select * from @TempTable
0 голосов
/ 22 января 2019

Вы можете попробовать использовать cte recursive с функцией DATEADD.

;WITH CTE AS(
    SELECT DATEADD (DAY,1,COLUMN1) COLUMN1,COLUMN2
    FROM T
    UNION ALL
    SELECT DATEADD (DAY,1,COLUMN1) ,COLUMN2
    FROM CTE
    WHERE  DATEADD (DAY,1,COLUMN1)< COLUMN2
)
SELECT COLUMN1 
FROM CTE
ORDER BY COLUMN1

sqlfiddle

...