编辑涵盖所有案例
我对SQL(SQL Server 2008)相对较新,我的问题陈述如下。表中的数据可以包含重叠的持续时间,但这需要分离出来(在样本数据集下面)
表中的数据如下:
Column 1 |Column 2 |StartTime |EndTime |Factor
A |B |Jan 1 |Jun 30 |0.7
A |B |Feb 1 |September 30|0.3
A |B |Mar 1 |August 31 |0.2
所需的输出如下:
Column 1 |Column 2 |StartTime |EndTime |Factor
A |B |Jan 1 |Jan 31 |0.7
A |B |Feb 1 |Feb 28 |1.0
A |B |Mar 1 |Jun 30 |1.2
A |B |Jul 1 |August 31 |0.5
A |B |Sept 1 |Sept 30 |0.3
要求是每当第1列和第2列相同并且日期重叠时,应该将因子加总,并且应该创建具有新的开始和结束时间的新记录,以便存在连续性。 / p>
开始和结束时间采用DATETIME格式。
我尝试使用自联接,但没有到达任何地方。有没有人有任何建议?
答案 0 :(得分:0)
DECLARE @MD AS int;
SELECT @MD = MAX(YEAR(a2.STARTTIME) * 100 + MONTH(a2.ENDTIME)) FROM ashtable a2;
WITH MTHS AS (
SELECT MIN(YEAR(STARTTIME) * 100 + MONTH(STARTTIME)) TheMonth FROM ashtable
UNION ALL
SELECT TheMonth + 1 FROM MTHS WHERE TheMonth < @MD
),
ALLMONTHS AS
(
select a.Column1,a.column2,m.TheMonth, SUM(FACTOR) f from mths m
LEFT JOIN
ashtable a
ON m.TheMonth >= YEAR(a.STARTTIME) * 100 + MONTH(a.STARTTIME)
AND
m.TheMonth <= YEAR(a.ENDTIME) * 100 + MONTH(a.ENDTIME)
GROUP BY a.Column1,a.column2, m.TheMonth
),
RNS AS
(SELECT a.Column1,a.column2,a.TheMonth, a.f, a.f - COALESCE(b.f, -99999999.99) dif FROM ALLMONTHS a
LEFT JOIN ALLMONTHS b ON a.TheMonth = b.TheMonth + 1 AND a.column1=b.column1 and a.column2=b.column2),
ISLANDS AS (
select a.Column1,a.column2,a.TheMonth,
MIN(b.TheMonth) MonthEnd,
MIN(A.f) Factor
from RNS a
LEFT JOIN RNS b ON a.column1=b.column1 and a.column2=b.column2 and b.TheMonth > a.TheMonth AND b.f <> a.f WHERE a.dif <> 0
GROUP BY a.column1,a.column2,a.TheMonth
)
SELECT Column1,column2,dateadd(month, (themonth - 1) % 100,
DateADD(year,(Themonth) / 100 - 1900, 0)) s,
dateadd(day,-1,dateadd(month, (themonth) % 100,
DateADD(year,(Themonth) / 100 - 1900, 0))) e, factor FROM ISLANDS order by column1,column2,s
我的输出(包括不同列键的测试行)
Column1 column2 s e factor
---------- ---------- ----------------------- ----------------------- -------
A B 2016-01-01 00:00:00.000 2016-01-31 00:00:00.000 0.7
A B 2016-02-01 00:00:00.000 2016-02-29 00:00:00.000 1.0
A B 2016-03-01 00:00:00.000 2016-03-31 00:00:00.000 1.2
A B 2016-07-01 00:00:00.000 2016-07-31 00:00:00.000 0.5
A B 2016-09-01 00:00:00.000 2016-09-30 00:00:00.000 0.3
A C 2016-01-01 00:00:00.000 2016-01-31 00:00:00.000 99.0
这是一个修改过的版本,抛弃了我将失败的想法表示为整数
DECLARE @MD AS datetime;
SELECT @MD = MAX(endtime) FROM ashtable a2;
WITH MTHS AS (
SELECT MIN(STARTTIME) TheMonth FROM ashtable
UNION ALL
SELECT dateadd(month,1,TheMonth) TheMonth FROM MTHS WHERE TheMonth < @MD
),
ALLMONTHS AS
(
select a.Column1,a.column2,m.TheMonth, SUM(FACTOR) f from mths m
LEFT JOIN
ashtable a
ON m.TheMonth >= a.starttime
AND
m.TheMonth < a.endtime
GROUP BY a.Column1,a.column2, m.TheMonth
),
RNS AS
(SELECT a.Column1,a.column2,a.TheMonth, a.f, a.f - COALESCE(b.f, -99999999.99) dif FROM ALLMONTHS a
LEFT JOIN ALLMONTHS b ON a.TheMonth = dateadd(month,1,b.TheMonth) AND a.column1=b.column1 and a.column2=b.column2),
ISLANDS AS (
select a.Column1,a.column2,a.TheMonth,dq2.lastmonth,a.f factor
from RNS a
CROSS APPLY
(SELECT TOP 1 * FROM (SELECT 1 as ord, b.TheMonth lastmonth FROM RNS b WHERE a.Column1 = b.column1 and a.column2=b.column2 and b.themonth>a.themonth and a.f <> b.f
union SELECT 2 as ord, dateadd(month,1,max(c.themonth)) lastmonth from rns c where a.Column1 = c.column1 and a.column2=c.column2) dq ORDER BY DQ.ord) dq2
where a.dif<>0
--MIN(b.TheMonth) MonthEnd,
--MIN(A.f) Factor
-- from RNS a
-- LEFT JOIN RNS b ON a.column1=b.column1 and a.column2=b.column2 and b.TheMonth > a.TheMonth AND b.f <> a.f where a.dif<>0
-- GROUP BY a.column1,a.column2,a.TheMonth
)
SELECT Column1,column2,themonth, dateadd(day,-1,lastmonth),
factor FROM ISLANDS order by column1,column2,themonth