我必须将两个表合并为一个,但我必须将验证日期纳入考虑范围。例如有两个表:
Address
ID AddressValue ValidFrom ValidTo
----------- --------------- ----------------------- -----------------------
1 Pink Street 2010-01-01 00:00:00.000 2010-01-20 00:00:00.000
2 Yellow Street 2010-01-20 00:00:00.000 2010-02-28 00:00:00.000
Phone
ID PhoneValue ValidFrom ValidTo
----------- ------------ ----------------------- -----------------------
1 123456789 2010-01-01 00:00:00.000 2010-01-15 00:00:00.000
2 987654321 2010-01-16 00:00:00.000 2010-01-31 00:00:00.000
我需要将它们组合成新的:
NewSystem
ID NewPhone NewAddress ValidFrom ValidTo Version
----------- ----------- --------------- ----------------------- ----------------------- -------
1 123456789 Pink Street 2010-01-01 00:00:00.000 2010-01-15 00:00:00.000 4
2 NULL Pink Street 2010-01-15 00:00:00.000 2010-01-16 00:00:00.000 3
3 987654321 Pink Street 2010-01-16 00:00:00.000 2010-01-20 00:00:00.000 2
4 987654321 Yellow Street 2010-01-20 00:00:00.000 2010-01-31 00:00:00.000 1
5 NULL Yellow Street 2010-01-31 00:00:00.000 2010-02-28 00:00:00.000 0
这个想法非常简单。我根据日期创建句点,然后查询子查询中的每个表。我在此处粘贴了我的解决方案:http://pastebin.com/cdKePA9X。
现在我正试图摆脱光标,但我失败了。我试图使用CTE但没有成功。也许有人遇到类似的问题,或者知道如何在不使用游标的情况下将这些表组合成一个。我在这里粘贴了“创建表”脚本:http://pastebin.com/BeRspb6K。
先谢谢你。
答案 0 :(得分:1)
首先,通过合并源表中的日期范围来构造新的日期范围。其次,对于每个新的日期范围,查找源表中的有效数据。
WITH
old_ranges(d1,d2) AS (
SELECT ValidFrom,ValidTo FROM @Address UNION
SELECT ValidFrom,ValidTo FROM @Phone
),
new_ranges(d1,d2) AS (
SELECT d,LEAD(d) OVER(ORDER BY d)
FROM (
SELECT DISTINCT d
FROM old_ranges
UNPIVOT(d FOR dx IN (d1,d2)) p
) t
)
SELECT
ROW_NUMBER() OVER (ORDER BY d1) AS ID,
NewPhone,
NewAddress,
d1 AS ValidFrom,
d2 AS ValidTo
FROM new_ranges
OUTER APPLY (
SELECT PhoneValue AS NewPhone
FROM @Phone
WHERE ValidFrom <= d1 AND ValidTo >= d2
) x1
OUTER APPLY (
SELECT AddressValue AS NewAddress
FROM @Address
WHERE ValidFrom <= d1 AND ValidTo >= d2
) x2
WHERE d2 IS NOT NULL