Хитрость здесь в том, чтобы оговорить «а между потерянными и найденными датами нет другой потерянной или найденной даты» или, в SQL:
SELECT c0.ItemId, c0.ChangeDate, c1.ChangeDate
FROM Changes AS c0
JOIN Changes AS c1 ON c0.ItemId = c1.ItemId AND c1.ChangeDate >= c0.ChangeDate
WHERE c0.ChangeType = 9 -- Lost
AND c1.ChangeType = 10 -- Found
AND NOT EXISTS(SELECT *
FROM Changes AS c2
WHERE c2.ItemId = c1.ItemID
AND c2.ChangeType IN (9, 10) -- Lost or Found
AND c2.ChangeDate BETWEEN c0.ChangeDate AND c1.ChangeDate
AND (c2.ChangeDate != c0.ChangeDate AND c2.ChangeDate != c1.ChangeDate)
);
Поскольку это коррелированный подзапрос,он имеет тенденцию замедлять запрос, но должен давать правильные строки.
Существует важное предостережение о том, как я удалил строки c0 и c1, указав, что ChangeDate для строки в c2 долженотличаться от потерянной даты или найденной даты.Однако основной запрос, по-видимому, позволяет найти элемент в тот же день, когда он был утерян.Там может быть какой-то другой столбец, например столбец ChangeId, который не указан в запросе, но который можно использовать вместо этого:
AND c2.ChangeID NOT IN (c0.ChangeID, c1.ChangeID)
Вам нужно подумать о том, что произойдет, если элемент потерянскажем, 2011-06-07, и снова проиграл 2011-06-14, и был найден только 2011-06-21.А что, если он также найден на 2011-06-28?Такие проблемы должны быть предотвращены обработкой ввода данных, поэтому в приведенном выше запросе предполагается, что таких проблем не будет.