2011-12-19 82 views
0

表A(ID INT,MATCH1炭,MATCH2炭,MATCH3炭,開始日期日期時間,結束日期,狀態炭)日期重疊場景

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炭,MATCH2,MATCH3,開始日期日期時間,結束日期)

match1 match2 match3 startdate enddate 
AAA  BBB CCC  2006-01-01 2015-01-01 
DDD  EEE FFF  2009-01-01 2015-01-01 

好了,所以[統計]是NULL,我在表A與 'FAIL' 來填充STAT時:

1)對於TableB中匹配MATCH1,MATCH2,MATCH3,日期(開始和結束)存在於範圍之外。讓我們看看ID = 5 effectivedates = 2013 - 2020,但在其參考表中,其2009-2015因此ID = 5會得到'失敗'。

2)在一組中,set1是match1,match2,match3相等的記錄,所以ID123是一組,ID4是另一組。所以,在一組中,生效日期(開始和結束)日期重疊。即使第1組(ID1,2,3)存在於參考表中相應記錄的日期範圍內,但ID = 2的有效日期與ID = 1的有效日期重疊,因此ID = 2獲得了「FAIL」

預期的結果:

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

先取得第一個,然後「失敗」下一個重疊。 – 2011-12-19 21:52:30

+0

在ID 2和ID 2重疊的第二種情況下,您如何決定使ID 2的行「失敗」而不是ID 1的行?在這種情況下,你是否始終以失敗告終? – 2011-12-19 21:56:40

回答

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 

EDIT(我想我可能是過於簡單化) 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) 
+0

ANDREW:你的代碼失敗了ID 1,2,3,4,但它只會失敗2和5. – 2011-12-19 22:01:34

+0

此外,我們必須在[set]中匹配enddate od id1和id2的startdate,等等,你的代碼不會似乎沒有做到這一點。謝謝 – 2011-12-19 22:03:48

+0

對不起,我發現case1的另一個漏洞。讓我們假設1 2 3日期是2006-2008,2012-2014,2009-2010。現在即使這些日期並不相互重疊並存在於其引用記錄的範圍內,它仍然會失敗id = 3因爲TableA2.startDate 2011-12-19 23:43:58

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