这是我的问题:
我有一张桌子:
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 @cnt=@cnt - 1
SET @incr=@incr + 1
END
目前代码在输入表上有一行的情况下工作,但考虑到我需要在多行上迭代它,我目前还没有找到解决方案。这里有人知道谁可以帮我解决这个问题?
非常感谢你提前, 亲切的问候, 路易
答案 0 :(得分: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
答案 1 :(得分:0)
也许创建一个包含日期的日历表,然后加入它。
SELECT *
FROM input_table it
JOIN calendar c on c.date >= it.startdate and c.date <= it.enddate