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
;