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

У меня есть таблица 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 голосов
/ 29 августа 2018

Вы можете использовать ниже SQL Query for, чтобы получить свой результат. При этом использовались курсор и имена столбцов, а псевдоним может потребоваться изменить в соответствии с вашими требованиями.

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
0 голосов
/ 29 августа 2018

Попробуйте запрос ниже:

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);
0 голосов
/ 29 августа 2018

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.

0 голосов
/ 29 августа 2018

Вы можете сделать декартово соединение:

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 
0 голосов
/ 29 августа 2018
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]
0 голосов
/ 29 августа 2018

Используйте выбор ниже, чтобы получить даты, присоединитесь к таблице 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
...