TableA(id int,match1 char,match2 char,match3 char,startdate datetime,enddate,status char)
id match1 match2 match3 startdate enddate
1 AAA BBB CCC 2006-01-01 2007-01-01
2 AAA BBB CCC 2006-12-12 2008-01-01
3 AAA BBB CCC 2008-01-01 2012-02-02
4 DDD EEE FFF 2009-01-01 2012-01-01
5 DDD EEE FFF 2013-01-01 2020-01-01
参考表B(match1 char,match2,match3,startdate datetime,enddate)
match1 match2 match3 startdate enddate
AAA BBB CCC 2006-01-01 2015-01-01
DDD EEE FFF 2009-01-01 2015-01-01
好的,[Stat]为NULL,我必须在tableA中使用'FAIL'填充stat:
1)为了匹配tableB中的match1,match2,match3,日期(开始和结束)存在于范围之外。让我们看看ID = 5 effectivedates = 2013 - 2020但是在其参考表中,它的2009-2015所以ID = 5会得到'失败'。
2)在集合中,set是match1,match2,match3相等时的记录,因此ID 123是一组,ID 4& 5是另一组。因此,在一组中,有效日期(开始和结束)日期重叠。即使集合1(ID1,2,3)存在于参考表中其相应记录的日期范围内,但ID = 2的生效日期与ID = 1的生效日期重叠,因此ID = 2得到'失败'
预期结果:
id match1 match2 match3 startdate enddate stat
1 AAA BBB CCC 2006-01-01 2007-01-01 NULL
2 AAA BBB CCC 2006-12-12 2008-01-01 FAIL
3 AAA BBB CCC 2008-01-01 2012-02-02 NULL
4 DDD EEE FFF 2009-01-01 2012-01-01 NULL
5 DDD EEE FFF 2013-01-01 2020-01-01 FAIL
先谢谢。
答案 0 :(得分:1)
UPDATE tableA SET [status] = 'FAIL'
FROM tableB
WHERE tableB.match1 = tableA.match1
AND tableB.match2 = tableA.match2
AND tableB.match3 = tableA.match3
AND tableA.startDate >= tableB.startDate
AND tableA.endDate <= tableB.endDate
编辑(我认为我可能过于简单了)
EDIT2 - 改变了第二个WHERE
SELECT -- Things outside of allowed date range
id
FROM TableA
JOIN TableB ON TableB.match1 = TableA.match1
AND TableB.match2 = TableA.match2
AND TableB.match3 = TableA.match3
WHERE TableA.startDate < TableB.startDate
OR TableA.endDate > TableB.endDate
UNION
SELECT -- Things with overlapping date ranges
TableA2.id
FROM TableA
JOIN TableA AS TableA2 ON TableA2.match1 = TableA.match1
AND TableA2.match2 = TableA.match2
AND TableA2.match3 = TableA.match3
WHERE TableA2.startDate BETWEEN TableA.startDate AND TableA.endDate
OR TableA2.endDate BETWEEN TableA.startDate AND TableA.endDate
OR (TableA2.startDate < TableA.startDate AND TableA2.endDate > TableA.endDate)
答案 1 :(得分:1)
SQL声明
;WITH CandidateIDs AS (
SELECT idOriginal = YourTable.id, idFailCandidate = ed.id
FROM YourTable
INNER JOIN YourTable ed ON ed.match1 = YourTable.match1
AND ed.match2 = YourTable.match2
AND ed.startdate BETWEEN YourTable.startdate AND YourTable.enddate
AND ed.id <> YourTable.id
)
SELECT *
FROM YourTable
INNER JOIN (
SELECT idFailCandidate
FROM CandidateIDs r1
WHERE NOT EXISTS (SELECT * FROM CandidateIDs WHERE CandidateIDs.idFailCandidate = r1.idOriginal)
) fail ON fail.idFailCandidate = YourTable.id
测试脚本
;WITH YourTable (id, match1, match2, startdate, enddate, status) AS (
SELECT 1, 'AAA', 'BBB', CAST('2006-01-01' AS DATETIME), CAST('2007-01-01' AS DATETIME), NULL
UNION ALL SELECT 2, 'AAA', 'BBB', '2006-12-12', '2008-01-01', NULL
UNION ALL SELECT 3, 'AAA', 'BBB', '2008-01-01', '2012-02-01', NULL
UNION ALL SELECT 4, 'AAA', 'BBB', '2002-01-01', '2004-01-01', NULL
UNION ALL SELECT 5, 'DDD', 'EEE', '2009-01-01', '2012-01-01', NULL
UNION ALL SELECT 6, 'DDD', 'EEE', '2011-01-01', '2020-01-01', NULL
UNION ALL SELECT 7, 'DDD', 'EEE', '2013-01-01', '2015-01-01', NULL
UNION ALL SELECT 8, 'DDD', 'EFG', '2009-01-01', '2012-01-01', NULL
)
, CandidateIDs AS (
SELECT idOriginal = YourTable.id, idFailCandidate = ed.id
FROM YourTable
INNER JOIN YourTable ed ON ed.match1 = YourTable.match1
AND ed.match2 = YourTable.match2
AND ed.startdate BETWEEN YourTable.startdate AND YourTable.enddate
AND ed.id <> YourTable.id
)
SELECT *
FROM YourTable
INNER JOIN (
SELECT idFailCandidate
FROM CandidateIDs r1
WHERE NOT EXISTS (SELECT * FROM CandidateIDs WHERE CandidateIDs.idFailCandidate = r1.idOriginal)
) fail ON fail.idFailCandidate = YourTable.id