powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Как правильно наложить один диапазон дат на другой?
6 сообщений из 6, страница 1 из 1
Как правильно наложить один диапазон дат на другой?
    #39710398
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть таблица услуг: 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.
Услуга 1
  Подключена: 01.01.2015
  01.01.2015 - 01.03.2015
    Тариф: Тариф 1
    Активно: 50 суток
    Неактивно: 9 суток
  01.03.2015 - 01.04.2015
    Тариф: Тариф 2
    Активно: 31 сутки
    Неактивно: 0 суток
  01.04.2015 - 05.04.2015
    Тариф: Тариф 3
    Активно: 1 сутки
    Неактивно: 3 суток
  Удалена: 05.04.2015

Услуга 2
  Подключена: 01.01.2015
  01.01.2015 - 01.02.2015
    Тариф: Тариф 1
    Активно: 31 сутки
    Неактивно: 0 суток
  Отключена: 01.02.2015

На небольших объемах можно было бы сгенерировать календарь, на каждый день получить тариф и статус, а затем агрегировать периоды. Но во-первых данных у меня довольно много, а во-вторых даты это не DATE, а DATETIME и теоретически в течение дня по меньшей мере статусы могут меняться более одного раза.
Вместо ежедневного календаря можно было бы получить список всех distinct-значений DATE_BEG обоих исторических таблиц, но все-равно остается «во-первых» — объем данных будет большой.

Другим решением было бы двумя разными запросами отдельно посчитать периоды тарифов и периоды активности/неактивности, объединив затем результаты на клиенте.
Но в клиенте это делать не очень удобно, хотелось бы получить результат в одном запросе.

В крайнем случае длительность активности/неактивности не столь важна и ее можно вообще пропустить, то есть получать периоды только для тарифов. Но в этом случае мне нужно как-то получить дату удаления услуги. Как это лучше сделать, отдельный left join с дополнительным условием соединения STATUS_ID=-20 или есть более правильный способ?
...
Рейтинг: 0 / 0
Как правильно наложить один диапазон дат на другой?
    #39710748
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.,

дата удаления услуги одна, имхо искать вообще просто

SERVICE_STATUS дырок нет? и всегда 1,-1... (-20)?

авторв этом случае период действия не ограничен

сразу замените на макс дату, напр 30.12.9999


зы
данные луче представлять в виде with, так удобнее

.....
stax
...
Рейтинг: 0 / 0
Как правильно наложить один диапазон дат на другой?
    #39710756
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дырок в исторических данных нет, все диапазоны смежные.
Но диапазоны статусов и тарифов не совпадают.
В БД DATE_END изначально определено как null и пустое значение означает, что граница не задана.
Ранее я использовал выражение nvl(DATE_END,DATE'9999-01-01'), но данных довольно много и выражение (DATE_END is null or DATE_END > sysdate) гораздо эффективнее, т.к. в этом случае используются индексы.

Сейчас я сделал по последнему варианту — учитываю только историю тарифов, историю статусов игнорирую, а дату удаления услуги получаю отдельным джойном. В принципе работает удовлетворительно.
Но буду благодарен, если подскажите более эффективный способ на будущее.
...
Рейтинг: 0 / 0
Как правильно наложить один диапазон дат на другой?
    #39710757
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Staxи всегда 1,-1... (-20)?
Нет, есть и другие статусы, то мне нужно различать только три статуса: -20, положительный и отрицательный.
...
Рейтинг: 0 / 0
Как правильно наложить один диапазон дат на другой?
    #39710766
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alibek B.Сейчас я сделал по последнему варианту — учитываю только историю тарифов, историю статусов игнорирую, а дату удаления услуги получаю отдельным джойном. В принципе работает удовлетворительно.


ето обычная задача на пересечение интервалов (SERVICE_TARIFF,SERVICE_STATUS), где-то раз в месяц всплывает
в Вашем случае решается достаточно просто (надо акуратненько даты расписать greatest/least|case),
а вот наскоко ефективно зависит от схемы, данных и тд

зи
если есть правильные даты статусов, но непонятно зачем нужны даты в SERVICES

.....
stax
...
Рейтинг: 0 / 0
Как правильно наложить один диапазон дат на другой?
    #39710785
Alibek B
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
START_DATE и STOP_DATE имеют приоритет перед задаваемыми статусами.
Они задают срок действия услуги, при наступлении STOP_DATE система автоматически добавляет статус -10 в историю (то есть не удаляет услугу, а отключает ее).
В приведенном примере первая услуга была удалена, а вторая отключена по окончанию срока действия.
...
Рейтинг: 0 / 0
6 сообщений из 6, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Как правильно наложить один диапазон дат на другой?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]