Сценарий перекрытия дат - PullRequest
0 голосов
/ 20 декабря 2011

TableA (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

Ссылка TableB (символ match1, совпадение2, match3, дата-время начала, конечная дата)

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, мне нужно заполнить stat с помощью 'FAIL' в таблице A, когда:

1) Для сопоставления match1, match2, match3 в таблицеB, даты (начало и конец) существует за пределами области видимости.Давайте посмотрим ID = 5ffectivedates = 2013 - 2020, но в своей справочной таблице его 2009-2015 гг., Поэтому ID = 5 получает 'fail'.

2) В наборе набор - это записи, когда match1, match2,match3 равны, поэтому ID 123 - это один набор, а ID 4 и 5 - другой набор.Итак, в наборе даты вступления в силу (начальная и конечная) перекрываются.хотя набор 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

Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 29 декабря 2011

Оператор 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           
1 голос
/ 20 декабря 2011
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

РЕДАКТИРОВАТЬ (я подумал, что, возможно, слишком упрощенно) РЕДАКТИРОВАТЬ2 - второй изменил ГДЕ

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...