感谢您寻求帮助。我有一张这样的桌子。让我们称之为TableA
[Id] [CHAR](10) NOT NULL,
[DType] [SMALLINT] NOT NULL,
[PType] [CHAR](1) NOT NULL,
[Period] [INT] NOT NULL,
[FromDate] [SMALLDATETIME] NOT NULL,
[ToDate] [SMALLDATETIME] NOT NULL,
[Highval] [DECIMAL](19, 4) NULL,
主键是Id, DType, PType, Period, FromDate
其中有数据如下:
Id DType PType Period FromDate ToDate Highval
-------------------------------------------------------------------
000000000G 1 A 2015 2014-11-02 2014-11-04 0.4800
000000000G 1 A 2015 2014-11-01 2014-11-01 1.2860
000000000G 1 A 2015 2014-10-28 2014-10-31 1.2290
000000000K 4 2 2015 2014-12-17 2014-12-20 2.5800
000000000K 4 3 2015 2014-12-15 2014-12-16 2.1700
000000000K 4 3 2015 2014-11-14 2014-12-14 2.7200
我需要一种方法来分割日期范围,任何大于或等于FromDate且小于或等于ToDate的东西,我需要将它们分成另一个名为IndividualDate
的列到同一个表中。基本上,在给定的日期范围内,如果FromDate
和ToDate
之间存在日期,请在另一个名为IndividualDate
的列中写入日期。对于给定的Id
,DType
,PType
,PEnd
,FromDate
,FromDate
和ToDate
字段日期范围不有重复。因此,日期范围是完全分开的。上面的示例数据的最终输出表(临时表很好)将如下所示。
Id DType PType Period FromDate ToDate Highval IndividualDate
----------------------------------------------------------------------------------
000000000G 1 A 2015 2014-11-02 2014-11-04 0.4800 2014-11-02
000000000G 1 A 2015 2014-11-02 2014-11-04 0.4800 2014-11-03
000000000G 1 A 2015 2014-11-02 2014-11-04 0.4800 2014-11-04
000000000G 1 A 2015 2014-11-01 2014-11-01 1.2860 2014-11-01
000000000G 1 A 2015 2014-10-28 2014-10-31 1.2290 2014-10-28
000000000G 1 A 2015 2014-10-28 2014-10-31 1.2290 2014-10-29
000000000G 1 A 2015 2014-10-28 2014-10-31 1.2290 2014-10-30
000000000G 1 A 2015 2014-10-28 2014-10-31 1.2290 2014-10-31
000000000K 4 2 2015 2014-12-17 2014-12-20 2.5800 2014-12-17
000000000K 4 2 2015 2014-12-17 2014-12-20 2.5800 2014-12-18
000000000K 4 2 2015 2014-12-17 2014-12-20 2.5800 2014-12-19
000000000K 4 2 2015 2014-12-17 2014-12-20 2.5800 2014-12-20
000000000K 4 3 2015 2014-12-15 2014-12-16 2.1700 2014-12-15
000000000K 4 3 2015 2014-12-15 2014-12-16 2.1700 2014-12-16
000000000K 4 3 2015 2014-11-14 2014-12-14 2.7200 2014-12-14
任何建议都将不胜感激。提前谢谢。
答案 0 :(得分:1)
使用Recursive CTE
生成dates
DECLARE @maxdate DATE
SELECT @maxdate = Max(todate)
FROM Yourtable;
WITH cte
AS (SELECT Min(fromdate) Invidualdate
FROM Yourtable
UNION ALL
SELECT Dateadd(dd, 1, Invidualdate)
FROM cte
WHERE Invidualdate < @maxdate)
SELECT id,
DType,
PType,
Period,
FromDate,
ToDate,
Highval,
Invidualdate
FROM cte a
JOIN Yourtable b
ON a.Invidualdate BETWEEN b.FromDate AND b.ToDate
Option (maxrecursion 0)
或创建calender
表,这是一种更好的方法
create table calender(Individualdate date)
insert into calender values('2001-01-01'),....,('2020-12-31')
SELECT id,
DType,
PType,
Period,
FromDate,
ToDate,
Highval,
Individualdate
FROM calender a
JOIN yourtable b
ON a.Individualdate BETWEEN b.FromDate AND b.ToDate
答案 1 :(得分:1)
这个使用Tally Table
。供参考:http://www.sqlservercentral.com/articles/T-SQL/62867/
;WITH e1(N) AS(
SELECT 0 UNION ALL SELECT 0 UNION ALL SELECT 0 UNION ALL SELECT 0 UNION ALL SELECT 0 UNION ALL
SELECT 0 UNION ALL SELECT 0 UNION ALL SELECT 0 UNION ALL SELECT 0 UNION ALL SELECT 0
)
,e2(N) AS(SELECT 0 FROM e1 a, e1 b)
,e4(N) AS(SELECT 0 FROM e2 a, e2 b)
,Tally(N) AS(
SELECT TOP(SELECT MAX(DATEDIFF(DAY, FromDate, ToDate) + 1) FROM TableA) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM e4
)
SELECT
a.Id,
a.Dtype,
a.Ptype,
a.Period,
FromDate = CONVERT(VARCHAR(10), a.FromDate, 120),
ToDate = CONVERT(VARCHAR(10), a.ToDate, 120),
IndividualDate = CONVERT(VARCHAR(10), DATEADD(DAY, t.N -1, a.FromDate), 120)
FROM TableA a
CROSS JOIN Tally t
WHERE
t.N - 1 <= DATEDIFF(DAY, a.FromDate, a.ToDate)
ORDER BY a.Id, a.DType, a.PType, a.Period, a.Highval, IndividualDate