|
|
|
Как правильно наложить один диапазон дат на другой?
|
|||
|---|---|---|---|
|
#18+
Есть таблица услуг: SERVICES (SERVICE_ID, LOGIN, START_DATE, STOP_DATE). START_DATE и STOP_DATE задают период действия услуги, могут быть не заданы (в этом случае период действия не ограничен). У таблицы есть подчиненная таблица с историей тарифов: SERVICE_TARIFF (SERVICE_ID, TARIFF_ID, DATE_BEG, DATE_END). И еще у таблицы есть подчиненная таблица с историей состояний (статусов): SERVICE_STATUS (SERVICE_ID, STATUS_ID, DATE_BEG, DATE_END). Статус -20 соответствует удаленной записи (такой статус бывает только один в истории и он всегда последний), статус -1 соответствует отключенной услуге, статус 1 соответствует подключенной услуге. Я хочу в идеале получить такие данные: SERVICES SERVICE_IDLOGINSTART_DATESTOP_DATE1Услуга 12015-01-01-2Услуга 22015-01-012015-02-01 SERVICE_TARIFF SERVICE_IDTARIFF_IDDATE_BEGDATE_END112015-01-012015-03-01122015-03-012015-04-01132015-04-01-212015-01-01- SERVICE_STATUS SERVICE_IDSTATUS_IDDATE_BEGDATE_END112015-01-012015-02-201-12015-02-202015-03-01112015-03-012015-04-051-202015-04-05-212015-01-012015-02-012-12015-02-01- Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. На небольших объемах можно было бы сгенерировать календарь, на каждый день получить тариф и статус, а затем агрегировать периоды. Но во-первых данных у меня довольно много, а во-вторых даты это не DATE, а DATETIME и теоретически в течение дня по меньшей мере статусы могут меняться более одного раза. Вместо ежедневного календаря можно было бы получить список всех distinct-значений DATE_BEG обоих исторических таблиц, но все-равно остается «во-первых» — объем данных будет большой. Другим решением было бы двумя разными запросами отдельно посчитать периоды тарифов и периоды активности/неактивности, объединив затем результаты на клиенте. Но в клиенте это делать не очень удобно, хотелось бы получить результат в одном запросе. В крайнем случае длительность активности/неактивности не столь важна и ее можно вообще пропустить, то есть получать периоды только для тарифов. Но в этом случае мне нужно как-то получить дату удаления услуги. Как это лучше сделать, отдельный left join с дополнительным условием соединения STATUS_ID=-20 или есть более правильный способ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.09.2018, 22:46 |
|
||
|
Как правильно наложить один диапазон дат на другой?
|
|||
|---|---|---|---|
|
#18+
Alibek B., дата удаления услуги одна, имхо искать вообще просто SERVICE_STATUS дырок нет? и всегда 1,-1... (-20)? авторв этом случае период действия не ограничен сразу замените на макс дату, напр 30.12.9999 зы данные луче представлять в виде with, так удобнее ..... stax ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.10.2018, 09:16 |
|
||
|
Как правильно наложить один диапазон дат на другой?
|
|||
|---|---|---|---|
|
#18+
Дырок в исторических данных нет, все диапазоны смежные. Но диапазоны статусов и тарифов не совпадают. В БД DATE_END изначально определено как null и пустое значение означает, что граница не задана. Ранее я использовал выражение nvl(DATE_END,DATE'9999-01-01'), но данных довольно много и выражение (DATE_END is null or DATE_END > sysdate) гораздо эффективнее, т.к. в этом случае используются индексы. Сейчас я сделал по последнему варианту — учитываю только историю тарифов, историю статусов игнорирую, а дату удаления услуги получаю отдельным джойном. В принципе работает удовлетворительно. Но буду благодарен, если подскажите более эффективный способ на будущее. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.10.2018, 09:27 |
|
||
|
Как правильно наложить один диапазон дат на другой?
|
|||
|---|---|---|---|
|
#18+
Staxи всегда 1,-1... (-20)? Нет, есть и другие статусы, то мне нужно различать только три статуса: -20, положительный и отрицательный. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.10.2018, 09:29 |
|
||
|
Как правильно наложить один диапазон дат на другой?
|
|||
|---|---|---|---|
|
#18+
Alibek B.Сейчас я сделал по последнему варианту — учитываю только историю тарифов, историю статусов игнорирую, а дату удаления услуги получаю отдельным джойном. В принципе работает удовлетворительно. ето обычная задача на пересечение интервалов (SERVICE_TARIFF,SERVICE_STATUS), где-то раз в месяц всплывает в Вашем случае решается достаточно просто (надо акуратненько даты расписать greatest/least|case), а вот наскоко ефективно зависит от схемы, данных и тд зи если есть правильные даты статусов, но непонятно зачем нужны даты в SERVICES ..... stax ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.10.2018, 09:45 |
|
||
|
Как правильно наложить один диапазон дат на другой?
|
|||
|---|---|---|---|
|
#18+
START_DATE и STOP_DATE имеют приоритет перед задаваемыми статусами. Они задают срок действия услуги, при наступлении STOP_DATE система автоматически добавляет статус -10 в историю (то есть не удаляет услугу, а отключает ее). В приведенном примере первая услуга была удалена, а вторая отключена по окончанию срока действия. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.10.2018, 10:17 |
|
||
|
|

start [/forum/topic.php?fid=52&msg=39710398&tid=1883390]: |
0ms |
get settings: |
8ms |
get forum list: |
14ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
45ms |
get topic data: |
9ms |
get forum data: |
3ms |
get page messages: |
37ms |
get tp. blocked users: |
1ms |
| others: | 249ms |
| total: | 372ms |

| 0 / 0 |
