2016-11-16 62 views
0

这里是我的问题:拆分多个数据范围多行

我有一个表:

FIELD_1 FIELD_2 FIELD_N StartDate  EndDate  OTHER_FIELDS 
value1 value2 valuen 2016-01-12 2016-05-12 othervalues 
value3 value4 valuen 2015-01-12 2015-05-12 othervalues 

我需要分割在其他多行多行的数据范围。

如下:

StartDate     EndDate     other_columns 
2016-01-12    2016-05-12    myvalues 
2016-01-13    2016-05-12    myvalues 
2016-01-14    2016-05-12    myvalues 
..      ..      .. 
..      ..      .. 
2015-01-12    2015-05-12    myvalues 
2015-01-13    2015-05-12    myvalues 
..      ..      .. 

这里是我的代码:

CREATE TABLE [dbo].[OUTPUT_TABLE](
    [STARTDATE] [datetime] NULL, 
    [ENDDATE] [datetime] NULL, 
    [OTHER_FIELDS] [nvarchar](30) NULL, 
) ON [PRIMARY] 

GO 

DECLARE @cnt INT 
DECLARE @startDate DATETIME 
DECLARE @endDate DATETIME 
DECLARE @incr INT 
DECLARE @tempDate DATETIME 

SET @startDate=(SELECT [StartDate] 
       FROM [dbo].[INPUT_TABLE]) 
SET @endDate=(SELECT [EndDate] 
       FROM [dbo].[INPUT_TABLE]) 
SET @cnt=Datediff(dd, @startDate, @endDate) 
SET @incr=0 
SET @tempDate=Dateadd(dd, @incr, Cast(@startDate AS DATETIME)) 

WHILE @cnt >= 0 
    BEGIN 
     IF @cnt = 0 
     BEGIN 
      INSERT INTO [dbo].[OUTPUT_TABLE] 
      VALUES  (@tempDate, 
         @endDate, 
         NULL 
         ); 
     END 
     ELSE 
     BEGIN 
      INSERT INTO [dbo].[OUTPUT_TABLE] 
      VALUES  (@tempDate, 
         Dateadd(dd, Datediff(dd, 0, @tempDate) + 1, -1), 
         NULL 
         ); 
     END 


     SET @tempDate=Dateadd(dd, @incr + 1, Dateadd(dd, Datediff(dd, 0, 
                 @startDate) 
              , 0)) 
     SET @[email protected] - 1 
     SET @[email protected] + 1 
    END 

在代码在其上输入表中的一行的情况下工作的时刻,但考虑到我需要迭代它在多行我目前没有创建一个解决方案。这里的任何人都知道谁可以帮我解决这个问题?

非常感谢你提前, 亲切的问候, 路易吉

+0

所以你想在这些日期范围之间的每一天的行? – SQLChao

+0

是的,正好。对于多行.. – LuigiVe

+0

我认为你只是想在两个日期之间为每个日期插入一行?为此,你需要的是一张理货表。这里根本不需要任何循环。这里是关于这个话题的一篇很棒的文章。 http://www.sqlservercentral.com/articles/T-SQL/62867/ –

回答

0

可能创建一个包含日期的日历表,然后快快加入吧。

SELECT * 
FROM input_table it 
JOIN calendar c on c.date >= it.startdate and c.date <= it.enddate 
1

下面介绍如何利用理货表来简化这一工作。根本不需要循环。如果需要,您可以随时用ctes创建一个理货表。在我的系统中,我有一个像这样定义的视图。

create View [dbo].[cteTally] as 

WITH 
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)), 
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows 
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max 
    cteTally(N) AS 
    (
     SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4 
    ) 
select N from cteTally 

你真的应该非常熟悉理货表。它被称为“t-sql的瑞士军刀”。

现在我们需要表格和数据来最终确定问题。

create table #InputTable 
(
    SomeID int identity primary key 
    , StartDate date 
    , EndDate date 
    , OTHER_FIELDS varchar(20) 
) 

insert #InputTable 
(
    StartDate 
    , EndDate 
    , OTHER_FIELDS 
) 
select '2016-01-12', '2016-05-12', 'othervalues' union all 
select '2015-01-12', '2015-05-12', 'othervalues' 

CREATE TABLE [dbo].[OUTPUT_TABLE](
    [STARTDATE] [datetime] NULL, 
    [ENDDATE] [datetime] NULL, 
    ThisDate date, 
    [OTHER_FIELDS] [nvarchar](30) NULL, 
) ON [PRIMARY] 

现在我们对整个问题的设置,我们实际上可以开始解决方案的工作。利用统计表使这非常简单。无非是一个插入语句。

insert OUTPUT_TABLE 
(
    STARTDATE 
    , ENDDATE 
    , ThisDate 
    , OTHER_FIELDS 
) 
select it.StartDate 
    , it.EndDate 
    , DATEADD(day, t.N - 1, it.StartDate) 
    , it.OTHER_FIELDS 
from #InputTable it 
join cteTally t on t.N <= DATEDIFF(day, it.StartDate, it.EndDate) + 1 

现在我们可以检查一下,看看它是否按照我们认为应该的方式工作。

select * 
from OUTPUT_TABLE 

看看那个。 243行,每个日期在基表的每个开始日期和结束日期的值之间。没有循环,没有游标。留下的只是一些清理工作,以消除我们的跑腿证据。

drop table OUTPUT_TABLE 
drop table #InputTable