Самый простой способ заполнить временную таблицу датами между двумя параметрами даты включительно - PullRequest
21 голосов
/ 19 октября 2011

Какой самый простой способ заполнить временную таблицу датами, включая 2 параметра даты и между ними. Мне нужны только даты 1-го числа месяца.

Например, если @StartDate = '2011-01-01' и @EndDate = '2011-08-01'

Тогда я хочу вернуть это в таблицу

2011-01-01
2011-02-01
2011-03-01
2011-04-01
2011-05-01
2011-06-01
2011-07-01
2011-08-01

Ответы [ 8 ]

24 голосов
/ 19 октября 2011

Это работает, даже если @StartDate не первое число месяца. Я предполагаю, что если это не начало месяца, вы хотите начать с первого в следующем месяце. В противном случае удалите +1.:

;WITH cte AS (
SELECT CASE WHEN DATEPART(Day,@StartDate) = 1 THEN @StartDate 
            ELSE DATEADD(Month,DATEDIFF(Month,0,@StartDate)+1,0) END AS myDate
UNION ALL
SELECT DATEADD(Month,1,myDate)
FROM cte
WHERE DATEADD(Month,1,myDate) <=  @EndDate
)
SELECT myDate
FROM cte
OPTION (MAXRECURSION 0)
15 голосов
/ 31 мая 2014
declare @StartDate date = '2014-01-01';
declare @EndDate date = '2014-05-05';

;WITH cte AS (
    SELECT @StartDate AS myDate
    UNION ALL
    SELECT DATEADD(day,1,myDate) as myDate
    FROM cte
    WHERE DATEADD(day,1,myDate) <=  @EndDate
)
SELECT myDate
FROM cte
OPTION (MAXRECURSION 0)
7 голосов
/ 19 октября 2011
declare @StartDate datetime
declare @EndDate datetime
select @StartDate = '2011-01-01' ,  @EndDate = '2011-08-01'

select @StartDate= @StartDate-(DATEPART(DD,@StartDate)-1)

declare @temp  table
(
TheDate datetime
)
while (@StartDate<=@EndDate)
begin
insert into @temp
values (@StartDate )
select @StartDate=DATEADD(MM,1,@StartDate)
end
select * from @temp

Работает, даже если @StartDate не первый день месяца, возвращаясь к начальному дню месяца StartDate

6 голосов
/ 23 апреля 2015

это проверено в SQL 2008 R2

Declare @StartDate datetime = '2015-03-01'
Declare @EndDate datetime = '2015-03-31'
declare @temp Table
(
DayDate datetime
);

WHILE @StartDate <= @EndDate
begin
 INSERT INTO @temp (DayDate) VALUES (@StartDate);
 SET @StartDate = Dateadd(Day,1, @StartDate);
end ;

select * from @temp

Результат:

DayDate
-----------------------
2015-03-01 00:00:00.000
2015-03-02 00:00:00.000
2015-03-03 00:00:00.000
2015-03-04 00:00:00.000
...
1 голос
/ 28 июня 2017

Исправление для нулевых дат:

IF OBJECT_ID('tempdb..#dim') IS NOT NULL 

    DROP TABLE #dim

CREATE  TABLE #dim ([date] DATE)

if not @Begin_Date is null and not @End_Date is null

begin
    INSERT #dim([date])
    SELECT d
    FROM(

      SELECT
          d = DATEADD(DAY, rn - 1, @Begin_Date)
      FROM 
      (
          SELECT TOP (DATEDIFF(DAY, @Begin_Date, @End_Date)) 
              rn = ROW_NUMBER() OVER (ORDER BY s1.[object_id])
          FROM
              sys.all_objects AS s1
          CROSS JOIN
              sys.all_objects AS s2
          ORDER BY
              s1.[object_id]
      ) AS x
    ) AS y;
end
1 голос
/ 22 июля 2016

Интересно, что из перечисленных данных быстрее создавать согласно этой статье .

DECLARE @StartDate DATE = '10001201';
DECLARE @EndDate DATE   = '20000101';

DECLARE @dim TABLE ([date] DATE)

INSERT @dim([date])
SELECT d
FROM
(
  SELECT
      d = DATEADD(DAY, rn - 1, @StartDate)
  FROM 
  (
      SELECT TOP (DATEDIFF(DAY, @StartDate, @EndDate)) 
          rn = ROW_NUMBER() OVER (ORDER BY s1.[object_id])
      FROM
          sys.all_objects AS s1
      CROSS JOIN
          sys.all_objects AS s2
      ORDER BY
          s1.[object_id]
  ) AS x
) AS y;

На моей машине это примерно на 60% быстрее с большими диапазонами дат.Метод рекурсии может заполнить данные за 2000 лет примерно за 3 секунды и выглядит намного лучше, поэтому я не рекомендую этот метод только для увеличения дней.

1 голос
/ 19 октября 2011

Решение:

DECLARE  @StartDate DATETIME
        ,@EndDate DATETIME;

SELECT   @StartDate = '20110105'
        ,@EndDate = '20110815';

SELECT  DATEADD(MONTH, DATEDIFF(MONTH, 0, DATEADD(MONTH, v.number, @StartDate)), 0) AS FirstDay
--or Andriy M suggestion:
--SELECT    DATEADD(MONTH, DATEDIFF(MONTH, 0, @StartDate) + v.number, 0) AS FirstDay
INTO    #Results
FROM    master.dbo.spt_values v
WHERE   v.type = 'P'        
AND     DATEDIFF(MONTH, @StartDate, @EndDate) >= v.number;

SELECT  *
FROM    #Results;

DROP TABLE #Results;

Результаты:

FirstDay
-----------------------
2011-01-01 00:00:00.000
2011-02-01 00:00:00.000
2011-03-01 00:00:00.000
2011-04-01 00:00:00.000
2011-05-01 00:00:00.000
2011-06-01 00:00:00.000
2011-07-01 00:00:00.000
2011-08-01 00:00:00.000
0 голосов
/ 03 февраля 2019
CREATE TABLE #t (d DATE)

INSERT INTO #t SELECT GETDATE()

GO

INSERT #t SELECT DATEADD(DAY, -1, MIN(d)) FROM #t

GO 10
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...