如何为从SQL中的两个日期列中提取的日期范围生成所有日期

时间:2018-08-29 10:20:31

标签: sql date-range

我的表TEMP1为:

Parameter   Val From         To
a           1   8/1/2018    8/5/2018
b           2   8/4/2018    8/8/2018
c           3   8/8/2018    8/13/2018

我需要如下输出:

Parameter   Date    Val
a   8/1/2018    1
a   8/2/2018    1
a   8/3/2018    1
a   8/4/2018    1
a   8/5/2018    1
b   8/4/2018    2
b   8/5/2018    2
b   8/6/2018    2
b   8/7/2018    2
b   8/8/2018    2
c   8/8/2018    3
c   8/9/2018    3
c   8/10/2018   3
c   8/11/2018   3
c   8/12/2018   3
c   8/13/2018   3

使用SQL。

6 个答案:

答案 0 :(得分:1)

使用下面的选择获取日期,并加入TEMP1表以获取所需的值。

CREATE TABLE #tmpDates(  StartDate DATETIME, EndDate DATETIME  )

INSERT INTO #tmpDates (StartDate, EndDate)VALUES(   '2018-08-10', '2018-08-15')
GO

WITH myDates AS
(SELECT StartDate as aDate FROM #tmpDates AS td 
 UNION ALL
 SELECT DATEADD(day, 1, aDate) AS aDate FROM myDates 
 INNER JOIN #tmpDates AS td ON myDates.aDate >= td.StartDate
 WHERE DATEADD(day, 1, aDate) <= td.EndDate)
SELECT aDate, 1 as aValue
FROM myDates
INNER JOIN (SELECT StartDate, EndDate FROM #tmpDates AS td ) AS i ON 1=1
OPTION (MAXRECURSION 0);

DROP TABLE #tmpDates

答案 1 :(得分:1)

DECLARE @StartDate DATE
DECLARE @EindDate DATE
SET @StartDate = '1990-01-01'  -- << user input >> --
SET @EindDate  = '2018-12-31'  -- << user input >> --

IF OBJECT_ID ('TEMPDB..#Date') IS NOT NULL DROP TABLE #Date
IF OBJECT_ID ('TEMPDB..#Date') IS NULL CREATE TABLE #Date (Date_ DATE)

INSERT INTO #Date VALUES (@StartDate)

WHILE @StartDate < @EindDate

BEGIN
INSERT INTO #Date
SELECT DATEADD (DD, 1, @StartDate) AS Date
SET @StartDate = DATEADD (DD, 1, @StartDate)
END;


SELECT * 
FROM #Date

CREATE TABLE #T (Parameter VARCHAR (10), VAL INT, [From] DATE, [To] Date)
INSERT INTO #T VALUES ('a', 1, '20180801', '20180805')
INSERT INTO #T VALUES ('b', 2, '20180804', '20180808')
INSERT INTO #T VALUES ('c', 3, '20180808', '20180813')

SELECT D.Date_, T.Parameter, T.VAL 
FROM #Date AS D
INNER JOIN #T AS T ON D.Date_ >= T.[From] AND D.Date_ <= T.[To]

答案 2 :(得分:1)

MySQL(V8之前的版本)不支持递归查询。您要做的就是将表格连接到数字表格。如果规模不大,您可以即时创建一个:

select t.parameter, (t.from + interval n - 1 day) day as date,
       t.val
from temp1 t join
     (select 1 as n union all
      select 2 as n union all
      select 3 as n union all
      select 4 as n union all
      select 5 as n
     ) n
     on t.from + interval n - 1 day <= t.to;

我应该注意,您也可以使用Calendar表来完成此操作。

答案 3 :(得分:0)

您可以进行笛卡尔联接:

http://sqlfiddle.com/#!18/03a13/6

SELECT  s.*
FROM temp1 s, (
  select 1  'temp'
  union all
  select  2
  union all
  select  3 
  union all
  select  4 
  union all
  select  5 
) ss 

答案 4 :(得分:0)

请尝试以下查询:

WITH cte AS
 (SELECT Parameter,Val,From as dateval 
  UNION ALL
  SELECT Parameter,Val,DATEADD(day, 1, dateval)
   FROM cte WHERE DATEADD(day, 1, dateval) <= To
 )
SELECT Parameter,Val,dateval
FROM cte
OPTION (MAXRECURSION 0);

答案 5 :(得分:0)

您可以使用下面的SQL查询来获取结果。 这是使用游标的,列名称和别名可能需要根据您的要求进行更改。

SET NOCOUNT ON
DECLARE @mindate date
DECLARE @maxdate date
DECLARE @parameter char(5)
DECLARE @value smallint
Declare @temp table( fromdate date, Parameter char(5),val smallint)
DECLARE cur_date CURSOR
STATIC FOR 
SELECT [from],[to], [parameter],[val] from temp1
OPEN cur_date
IF @@CURSOR_ROWS > 0
 BEGIN 
 FETCH NEXT FROM cur_date INTO @mindate,@maxdate,@parameter, @value
 WHILE @@Fetch_status = 0
 BEGIN
 INSERT INTO @temp
 SELECT  TOP (DATEDIFF(DAY, @mindate, @maxdate) + 1)
        Date = DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY a.object_id) - 1, @mindate), @parameter as Parameter, @value  as Val 
FROM    sys.all_objects a
        CROSS JOIN sys.all_objects b

 FETCH NEXT FROM cur_date INTO @mindate,@maxdate,@parameter, @value
 END
END
CLOSE cur_date
DEALLOCATE cur_date
SELECT * FROM @temp