Как отобразить все даты между двумя заданными датами в SQL

Использование SQL Server 2000. Если дата начала 06/23/2008, а дата окончания 06/30/2008

Затем мне нужен вывод запроса как

06/23/2008
06/24/2008
06/25/2008
.
.
.
06/30/2008

Я создал имена таблиц как целые числа, которые имеют 1 столбец, значения столбцов - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, затем я использовал указанный ниже запрос

Пробный запрос

SELECT DATEADD(d, H.i * 100 + T .i * 10 + U.i, '" & dtpfrom.Value & "') AS Dates 
  FROM integers H 
CROSS JOIN integers T 
CROSS JOIN integers U 
order by dates

В приведенном выше запросе отображается только 999 дат. 999 дат означает (365 + 365 + 269) только даты. Предположим, я хочу выбрать более 3 лет (с 01.01.2003 по 01.01.2008). Вышеупомянутый запрос не должен подходить.

Как изменить мой запрос? Или любой другой запрос доступен для вышеуказанного условия.

Пожалуйста, предоставьте мне запрос.


person Gopal    schedule 29.09.2009    source источник


Ответы (4)


Это даст вам до 100000 дней:

SELECT DATEADD(d, Y.i * 10000 + X.i * 1000 + H.i * 100 + T .i * 10 + U.i, '" & dtpfrom.Value & "') AS Dates 
FROM integers H 
CROSS JOIN integers T 
CROSS JOIN integers U 
CROSS JOIN integers X 
CROSS JOIN integers Y 
order by dates
person D'Arcy Rittich    schedule 29.09.2009

Я бы не стал зацикливаться на создании списка дат, использовать таблицу чисел (а не только таблицу значений от 0 до 9), они полезны для многих вещей: http://web.archive.org/web/20150411042510/http://sqlserver2000.databases.aspfaq.com/why-should-i-consider-using-an-auxiler-numbers-table.html С таблицей истинных чисел вы не Мне придется КРЕСТНО СОЕДИНЯТЬСЯ кучу раз и сделать запрос слишком сложным.

Чтобы этот метод работал, вам необходимо выполнить настройку единого расписания:

SELECT TOP 10000 IDENTITY(int,1,1) AS Number
    INTO Numbers
    FROM sys.columns s1
    CROSS JOIN sys.columns s2
ALTER TABLE Numbers ADD CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number)

После того, как таблица чисел настроена, используйте этот запрос:

SELECT
    @Start+Number-1
    FROM Numbers
    WHERE Number<=DATEDIFF(day,@Start,@End)+1

чтобы захватить их, сделайте:

DECLARE  @Start datetime
         ,@End  datetime
DECLARE @AllDates table
        (Date datetime)

SELECT @Start = '06/23/2008', @End = '06/30/2008'

INSERT INTO @AllDates
        (Date)
    SELECT
        @Start+Number-1
        FROM Numbers
        WHERE Number<=DATEDIFF(day,@Start,@End)+1

SELECT * FROM @AllDates

вывод:

Date
-----------------------
2008-06-23 00:00:00.000
2008-06-24 00:00:00.000
2008-06-25 00:00:00.000
2008-06-26 00:00:00.000
2008-06-27 00:00:00.000
2008-06-28 00:00:00.000
2008-06-29 00:00:00.000
2008-06-30 00:00:00.000

(8 row(s) affected)
person KM.    schedule 29.09.2009

Один из возможных способов (не говоря уже о том, что он лучший или самый эффективный) был бы примерно таким:

DECLARE @StartDate DATETIME
SET @StartDate = '06/23/2008'

DECLARE @EndDate DATETIME 
SET @EndDate = '06/30/2008'

DECLARE @TableOfDates TABLE(DateValue DATETIME)

DECLARE @CurrentDate DATETIME

SET @CurrentDate = @startDate

WHILE @CurrentDate <= @endDate
BEGIN
    INSERT INTO @TableOfDates(DateValue) VALUES (@CurrentDate)

    SET @CurrentDate = DATEADD(DAY, 1, @CurrentDate)
END

SELECT * FROM @TableOfDates

Это будет работать с любым количеством дат, с любым диапазоном дат и не требует специальной «вспомогательной» таблицы с целочисленными значениями.

Он сохраняет все соответствующие даты в переменной таблицы в памяти, поэтому вы можете использовать ее, например, для другой оператор SELECT или все, что вам нужно.

Марк

person marc_s    schedule 29.09.2009
comment
Это идеальный подход для версий до 2005 года, потому что вы не можете использовать CTE - подробности см. В комментариях к этому вопросу: stackoverflow.com/questions/1478951/ - person OMG Ponies; 29.09.2009
comment
Этот цикл будет намного медленнее, чем использование традиционной таблицы чисел, как описано в моем ответе. Если это одноразовая вещь, это можно будет использовать. однако, если вы создадите много диапазонов дат, используйте более эффективный метод без циклов. - person KM.; 29.09.2009
comment
Да, но вам не нужна дополнительная таблица номеров! А для всего 10 или 20 рядов я не знаю, насколько будет разница. - person marc_s; 29.09.2009
comment
нет, для маленьких наборов особой разницы не будет. однако при использовании подхода с использованием таблицы чисел вы можете интегрировать запрос в более крупный запрос, а с помощью этого метода цикла вы не можете. если вам нужно сгенерировать диапазоны дат для набора пар начала / конца, вам подойдет таблица Numbers. - person KM.; 29.09.2009

Видеть:

Почему мне следует рассмотреть возможность использования вспомогательной календарной таблицы?

Календарная таблица может значительно упростить разработку решений для любой бизнес-модели, которая включает даты. Последнее, что я проверил, до некоторой степени охватывает практически любую бизнес-модель, которую вы только можете придумать. К постоянным проблемам, требующим подробных, сложных и неэффективных методов, относятся следующие вопросы:

  • Сколько рабочих дней между x и y?
  • ...
person onedaywhen    schedule 29.09.2009
comment
Это метод хранилища данных, и, как вы говорите, он очень мощный. Однако его еще предстоит заселить. - person Hooloovoo; 29.09.2009