#sql #sql-server
#sql #sql-сервер
Вопрос:
Я хотел бы узнать, есть ли у меня перекрывающиеся временные срезы с одинаковым идентификатором и одинаковым именем. В следующем примере записи с id = 2 и name = c перекрываются. Запись с id = 1 предназначена только для демонстрации хорошего примера.
Данная таблица:
--- ------ ------- ------------ --------------
|id | name | value | validFrom | validTo |
--- ------ ------- ------------ --------------
|1 | a | 12 | 2019-01-01 | 9999-12-31 |
|1 | b | 34 | 2019-01-01 | 2019-10-31 |
|1 | b | 35 | 2019-11-01 | 9999-12-31 |
|1 | c | 13 | 2019-01-01 | 2025-12-31 |
|2 | a | 49 | 2019-01-01 | 9999-12-31 |
|2 | b | 99 | 2019-01-01 | 2034-12-31 |
|2 | c | 75 | 2019-01-01 | 2019-10-31 |
|2 | c | 84 | 2019-10-28 | 9999-12-31 |
|n | ... | ... | ... | ... |
--- ------ ------- ------------ --------------
ожидаемый результат:
--- ------
|id | name |
--- ------
|2 | c |
--- ------
Заранее спасибо за помощь!
Ответ №1:
Вы можете получить перекрывающиеся строки, используя exists
:
select t.*
from t
where exists (select 1
from t t2
where t2.id = t.id and
t2.name = t.name and
t2.value <> t.value and
t2.validTo > t.validFrom and
t2.validFrom < t.validTo
);
Если вам просто нужны id
name
комбинации /:
select distinct t.id, t.name
from t
where exists (select 1
from t t2
where t2.id = t.id and
t2.name = t.name and
t2.value <> t.value and
t2.validTo > t.validFrom and
t2.validFrom < t.validTo
);
Вы также можете сделать это с кумулятивным максимальным:
select t.*
from (select t.*,
max(validTo) over (partition by id, name
order by validFrom
rows between unbounded preceding and 1 preceding
) as prev_validTo
from t
) t
where prev_validTo >= validFrom;
Комментарии:
1. OP может включать значение равно для сравнения дат (
>=
вместо>
), если перекрытия периодов должны учитывать граничные дни.2. @EzLo . . . Это хороший момент. Основываясь на образце данных, я не думаю, что границы должны быть одинаковыми.
3. Я совершенно уверен, что если вы не включите сравнение столбцов значений (т. Е. t.value <> t2.value ), ваши запросы будут возвращать каждую строку.
4. @GordonLinoff третий пример работает для меня как шарм. К сожалению, первый пример возвращает все записи (также отдельные строки). Также второй пример, но причина
distinct
в том, что любая комбинация id-name возвращается только один раз.5. @JM_ . . . Это было верно для первых двух (которые были исправлены), но не для третьего.