T-sql получает все даты между двумя датами

Возможный дубликат:
Получение дат между диапазоном дат

Скажем, у меня есть две даты (только дата, а не время), и я хочу получить все даты между этими двумя датами включительно и вставить их в таблицу. Есть ли простой способ сделать это с помощью оператора SQL (т.е. Без цикла)?

Ex:
Date1: 2010-12-01
Date2: 2010-12-04

Table should have following dates:
2010-12-01, 2010-12-02, 2010-12-03, 2010-12-04

Ответы

Ответ 1

Предполагая SQL Server 2005+, используйте рекурсивный запрос:

WITH sample AS (
  SELECT CAST('2010-12-01' AS DATETIME) AS dt
  UNION ALL
  SELECT DATEADD(dd, 1, dt)
    FROM sample s
   WHERE DATEADD(dd, 1, dt) <= CAST('2010-12-04' AS DATETIME))
SELECT * 
  FROM sample

Возврат:

 dt
 ---------
 2010-12-01 00:00:00.000
 2010-12-02 00:00:00.000
 2010-12-03 00:00:00.000
 2010-12-04 00:00:00.000

Используйте CAST/CONVERT для форматирования, как вам нравится.

Использование параметров для начала и конца:

INSERT INTO dbo.YOUR_TABLE
  (datetime_column)
WITH sample AS (
    SELECT @start_date AS dt
    UNION ALL
    SELECT DATEADD(dd, 1, dt)
      FROM sample s
     WHERE DATEADD(dd, 1, dt) <= @end_date)
SELECT s.dt
  FROM sample s

Ответ 2

Вам нужна таблица чисел. Если у вас нет постоянного, это более эффективный способ генерации, чем использование рекурсивного CTE. Постоянный будет более эффективным, хотя до тех пор, пока он считывается из буферного кеша.

DECLARE @D1 DATE = '2010-12-01'
DECLARE @D2 DATE = '2010-12-04'

;WITH 
L0 AS (SELECT 1 AS c UNION ALL SELECT 1),
L1 AS (SELECT 1 AS c FROM L0 A CROSS JOIN L0 B),
L2 AS (SELECT 1 AS c FROM L1 A CROSS JOIN L1 B),
L3 AS (SELECT 1 AS c FROM L2 A CROSS JOIN L2 B),
L4 AS (SELECT 1 AS c FROM L3 A CROSS JOIN L3 B),
Nums AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS i FROM L4)
SELECT DATEADD(day,i-1,@D1)
 FROM Nums where i <= 1+DATEDIFF(day,@D1,@D2)

Ответ 3

Я просто сделал что-то вроде этого:

declare @dt datetime = '2010-12-01'
declare @dtEnd datetime = '2010-12-04'

WHILE (@dt < @dtEnd) BEGIN
    insert into table(datefield)
        values(@dt)
    SET @dt = DATEADD(day, 1, @dt)
END

Ответ 4

Повторный вопрос

Получение дат между диапазоном дат

DECLARE @DateFrom smalldatetime, @DateTo smalldatetime;
SET @DateFrom='20000101';
SET @DateTo='20081231';
-------------------------------
WITH T(date)
AS
( 
SELECT @DateFrom 
UNION ALL
SELECT DateAdd(day,1,T.date) FROM T WHERE T.date < @DateTo
)
SELECT date FROM T OPTION (MAXRECURSION 32767);