MS Sql 2008:
我有3个表:米,变压器(Ti)和电压互感器(Tu)
ParentId MeterId BegDate EndDate
10 100 '20050101' '20060101'
ParentId TiId BegDate EndDate
10 210 '20050201' '20050501'
10 220 '20050801' '20051001'
ParentId TuId BegDate EndDate
10 300 '20050801' '20050901'
其中日期格式为yyyyMMdd(年 - 月 - 日)
有没有办法让句点相交并像这样返回表格?
ParentId BegDate EndDate MeterId TiId TuId
10 '20050101' '20050201' 100 null null
10 '20050201' '20050501' 100 210 null
10 '20050501' '20050801' 100 null null
10 '20050801' '20050901' 100 220 300
10 '20050901' '20051001' 100 220 null
10 '20051001' '20060101' 100 null null
这是表创建脚本:
--meters
declare @meters table
(ParentId int,
MeterId int,
BegDate smalldatetime,
EndDate smalldatetime
)
insert @meters
select 10, 100, '20050101', '20060101'
--transformers
declare @ti table
(ParentId int,
TiId int,
BegDate smalldatetime,
EndDate smalldatetime
)
insert @ti
select 10, 210, '20050201', '20050501'
union all
select 10, 220, '20050801', '20051001'
--voltage transformers
declare @tu table
(ParentId int,
TuId int,
BegDate smalldatetime,
EndDate smalldatetime
)
insert @tu
select 10, 300, '20050801', '20050901'
答案 0 :(得分:3)
这应该有效:
这里发生的是我使用CTE(公用表表达式)来分解基于UNION的查询,该查询为我们提供了用于构建间隔的所有日期点。
完成此操作后,我们可以使用ROW_NUMBER()为我们提供相邻的日期对作为间隔,一旦我们拥有这些日期,就可以适当地加入您的数据。
希望这有帮助!
;WITH dates (dval) AS
(
SELECT DISTINCT begdate AS dval
FROM @meters m
UNION
SELECT DISTINCT enddate AS dval
FROM @meters m
UNION
SELECT DISTINCT begdate AS dval
FROM @ti ti
UNION
SELECT DISTINCT enddate AS dval
FROM @ti ti
UNION
SELECT DISTINCT begdate AS dval
FROM @tu tu
UNION
SELECT DISTINCT enddate AS dval
FROM @tu tu
)
SELECT m.Parentid, d1.dval AS begdate, d2.dval AS enddate, m.meterid, ti.tiid, tu.tuid
FROM
(
SELECT dval, ROW_NUMBER() OVER (ORDER BY dval ASC) AS rnum
FROM dates
) d1
INNER JOIN
(
SELECT dval, ROW_NUMBER() OVER (ORDER BY dval ASC) AS rnum
FROM dates
) d2 ON d1.rnum+1 = d2.rnum
LEFT JOIN @meters m ON m.begdate <= d1.dval AND m.enddate >= d2.dval
LEFT JOIN @ti ti ON ti.begdate <= d1.dval AND ti.enddate >= d2.dval
LEFT JOIN @tu tu ON tu.begdate <= d1.dval AND tu.enddate >= d2.dval
答案 1 :(得分:0)
mwigdahl,
十分感谢!
我刚刚修改了你的解决方案,以便在米表包含不同的parentid的行时使用ParentId,对于样本:
ParentId MeterId BegDate EndDate
10 100 '20050101' '20060101'
20 110 '20050201' '20050701'
这是脚本
--meters
DECLARE @Meters
TABLE (
ParentId INTEGER,
MeterId INTEGER,
BegDate SMALLDATETIME,
EndDate SMALLDATETIME
)
--transformers
DECLARE @TI
TABLE (
ParentId INTEGER,
TiId INTEGER,
BegDate SMALLDATETIME,
EndDate SMALLDATETIME
)
--voltage transformers
DECLARE @TU
TABLE (
ParentId INTEGER,
TuId INTEGER,
BegDate SMALLDATETIME,
EndDate SMALLDATETIME
)
INSERT @Meters (ParentId, MeterId, BegDate, EndDate)
SELECT 10, 100, '20050101', '20060101'
UNION ALL
SELECT 20, 110, '20050201', '20050701'
INSERT @TI (ParentId, TiId, BegDate, EndDate)
SELECT 10, 210, '20050201', '20050501'
UNION ALL
SELECT 10, 220, '20050801', '20051001'
UNION ALL
SELECT 20, 230, '20050101', '20050301'
UNION ALL
SELECT 20, 240, '20050501', '20051001'
INSERT @TU (ParentId, TuId, BegDate, EndDate)
SELECT 10, 300, '20050801', '20050901'
UNION ALL
SELECT 20, 310, '20050101', '20050601'
;with dM (ParentId, MeterId) as
(
select distinct ParentId, MeterId from @meters
),
dates (ParentId, meterid, dval) AS
(
SELECT ParentId, meterid, begdate AS dval
FROM @meters m
UNION
SELECT ParentId, meterid, enddate AS dval
FROM @meters m
UNION
SELECT ti.ParentId, meterid, begdate AS dval
FROM @ti ti
join dM dm on ti.ParentId = dm.ParentId
UNION
SELECT ti.ParentId, meterid, enddate AS dval
FROM @ti ti
join dM dm on ti.ParentId = dm.ParentId
UNION
SELECT tu.ParentId, meterid, begdate AS dval
FROM @tu tu
join dM dm on tu.ParentId = dm.ParentId
UNION
SELECT tu.ParentId, meterid, enddate AS dval
FROM @tu tu
join dM dm on tu.ParentId = dm.ParentId
)
select m.ParentId, d1.dval AS begdate, d2.dval AS enddate, m.MeterId, TiId, TuId
FROM
(
SELECT ParentId, meterid, dval, ROW_NUMBER() OVER (ORDER BY ParentId asc, meterid ASC, dval ASC) AS rnum
FROM dates
) d1
INNER JOIN
(
SELECT ParentId, meterid, dval, ROW_NUMBER() OVER (ORDER BY ParentId asc, meterid ASC, dval ASC) AS rnum
FROM dates
) d2 ON d1.ParentId = d2.ParentId and d1.meterid = d2.meterid and d1.rnum+1 = d2.rnum
LEFT JOIN @meters m ON m.ParentId = d1.ParentId and m.ParentId = d2.ParentId and m.meterid = d1.meterid and m.meterid = d2.meterid and m.begdate <= d1.dval AND m.enddate >= d2.dval
LEFT JOIN @ti ti ON ti.ParentId = d1.ParentId and ti.ParentId = d2.ParentId and ti.begdate <= d1.dval AND ti.enddate >= d2.dval
LEFT JOIN @tu tu ON tu.ParentId = d1.ParentId and tu.ParentId = d2.ParentId and tu.begdate <= d1.dval AND tu.enddate >= d2.dval
where not (m.ParentId is null) and not (m.meterid is null)
order by d1.ParentId, d1.MeterId, d1.dval, d2.dval
;