|
|
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
Есть список услуг. У услуг есть абонентская плата и характеристика периодичности услуги/абонплаты: ежесуточная, ежемесячная, ежегодная. Период может быть фиксированным (по границам месяца или года) или плавающим (по 20 числам месяца), кроме того он может быть кратным (каждые 5 дней, каждые 2 месяца). Например: УслугаАбонплатаПериодУслуга110ЕжедневноУслуга220Каждые 3 дняУслуга3200Каждый месяц (1-го числа)Услуга430010-го числа каждого месяцаУслуга5200020 февраля каждого года У услуги также есть статус (включена/выключена), он может изменяться в произвольные моменты времени (без привязки к периодичности услуги). Например: УслугаСтатусНачалоКонецУслуга1Включена2016-01-012016-02-01Услуга1Выключена2016-02-012016-02-20Услуга1Включена2016-02-20-Услуга2Включена2016-05-042016-05-20Услуга2Выключена2016-05-20-Услуга3Включена2016-02-012016-06-07Услуга3Выключена2016-06-07-Услуга4Включена2016-03-05-Услуга5Включена2016-03-022017-02-20 Задан период с Дата1 по Дата2 и мне нужно посчитать, какое количество дней в этом периоде услуга была включена, а также просуммировать долю абонплаты за этот период (другими словами — вычислить абонплату за сутки и просуммировать ее за периоды, пока услуга была включена). Я это делал следующим образом — разгруппировывал периоды (например период с 2016-02-01 по 2016-02-20 превращался в 20 дней с соответствующими датами), отбирал из этих дат период с Дата1 по Дата2, фильтровал по включенному статусу, а затем снова группировал, суммируя строки (дни) и суммы. Но это довольно накладно для сервера, запрос выполняется долго. Можно ли оптимизировать запрос таким образом, чтобы не "разворачивать" периоды в дни, а сразу отобрать только те периоды, когда услуга была включена, "обрезав" интервалы так, чтобы они не выходили за пределы Дата1-Дата2? ________________________ Мы смотрим с оптимизмом... ...в оптический прицел. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.09.2016, 15:07:39 |
|
||
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
Alibek B., Скока нонче платят в биллинговом бизнесе? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.09.2016, 15:48:38 |
|
||
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
А тупо просуммировать не вариант? Код: plsql 1. 2. 3. 4. 5. 6. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.09.2016, 16:03:20 |
|
||
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.09.2016, 16:04:39 |
|
||
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
Alibek B. Можно ли оптимизировать запрос таким образом, чтобы не "разворачивать" периоды в дни, а сразу отобрать только те периоды, когда услуга была включена, "обрезав" интервалы так, чтобы они не выходили за пределы Дата1-Дата2? Наоборот надо делать переводить период в интервал и умножать на стоимость единицы интервала для включенных услуг. автор________________________ Мы смотрим с оптимизмом... ...в оптический прицел. Будь я модератором , я бы тебя забанил за такую подписть , за ксенофобию . тут тебе не ПТ. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.09.2016, 16:15:16 |
|
||
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
andrey_anonymousА тупо просуммировать не вариант? Проверю, может быть и подойдет. Я когда уже опубликовал сообщение, тоже про такое подумал. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.09.2016, 17:38:56 |
|
||
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
д0kНаоборот надо делать переводить период в интервал Наоборот сделать нельзя, понятие интервала в Oracle не совпадает с понятием интервала в БС. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.09.2016, 17:52:47 |
|
||
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
Alibek B.д0kНаоборот надо делать переводить период в интервал Наоборот сделать нельзя, понятие интервала в Oracle не совпадает с понятием интервала в БС. Это конечно не мое дело , но если факты в БД , такие как как интервал использвания услуги с точки зрения клиента отличается от интервала в бизнес логике ПО , то компании используеющей такое ПО на открытом рынке не долго жить ... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.09.2016, 17:57:07 |
|
||
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
д0kто компании используеющей такое ПО на открытом рынке не долго жить ... Не хотелось бы разрушать стройную картину мира. Но мир сложнее, чем некоторые думают. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 29.09.2016, 19:02:37 |
|
||
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
Alibek B., 1) выбрасываем выключенные услуги 2) пересечения интервала услуги и диапазона расчета 3) для каждого типа услуги вычисляем число "срабатываний" (напр раз в неделю достаточно расплывчитое условие) 4) умножаем к-во на абонплату п.3 обычно обростает массой нюансов, напр 60-дней ето 2 месяца или все-таки меньше ..... stax ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2016, 13:33:07 |
|
||
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
stax..3) для каждого типа услуги вычисляем число "срабатываний" (напр раз в неделю достаточно расплывчитое условие) 4) умножаем к-во на абонплату Не понял про третий пункт. Что такое "число срабатываний"? Если доля времени работы услуги к ее общей длительности (например для услуги с месячной абонплатой если услуга была включена 15 дней, это будет 15/30), то там все довольно непросто, но у меня уже есть алгоритм, который дает те же результаты, что программный код БС. Были затруднения, как посчитать эту длительность просто в днях, но andrey_anonymous подсказал и вроде бы получается правильно. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2016, 17:04:12 |
|
||
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
Alibek B.stax..3) для каждого типа услуги вычисляем число "срабатываний" (напр раз в неделю достаточно расплывчитое условие) 4) умножаем к-во на абонплату Не понял про третий пункт. Что такое "число срабатываний"? Если доля времени работы услуги к ее общей длительности (например для услуги с месячной абонплатой если услуга была включена 15 дней, это будет 15/30), то там все довольно непросто, но у меня уже есть алгоритм, который дает те же результаты, что программный код БС. Были затруднения, как посчитать эту длительность просто в днях, но andrey_anonymous подсказал и вроде бы получается правильно. не знаю Вашего задания, напр Каждый месяц (1-го числа) период услуги 02-09-16 по 30-09-16 надо платить или нет Каждые 3 дня - виходные/праздничные учитывать или нет каждые 2 месяца - тож проблема что считать "полным" месяцем и тд ..... stax ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2016, 17:20:44 |
|
||
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
Alibek B.Не понял про третий пункт. Что такое "число срабатываний"? Hу нашел ты пересечения заданного периода (я бы не использовал терм интервал а то уже пошли ассоциации с типом данных) с периoдами включенной услуги. Но потом же тебе придется подсчитать сколько раз услуга попaдает в эти пересчения. Hапример для Услуга3 подсчитать сколько раз 1-го числo месяца попaдает в эти пересчения. Это и есть "число срабатываний". Кстати, формула "каждые 3 дня" недетерминирована. Нет точки отсчeта. SY. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2016, 17:33:41 |
|
||
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
SYКстати, формула "каждые 3 дня" недетерминирована. Нет точки отсчeта. Хотя возможно и нет, если точкa отсчeта начало периода. SY. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2016, 17:37:32 |
|
||
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
SYAlibek B.Не понял про третий пункт. Что такое "число срабатываний"? Hу нашел ты пересечения заданного периода (я бы не использовал терм интервал а то уже пошли ассоциации с типом данных) с периoдами включенной услуги. Но потом же тебе придется подсчитать сколько раз услуга попaдает в эти пересчения. Hапример для Услуга3 подсчитать сколько раз 1-го числo месяца попaдает в эти пересчения. Это и есть "число срабатываний". Кстати, формула "каждые 3 дня" недетерминирована. Нет точки отсчeта. SY. пересечение важно но дальше проблемы, имхо, луче оформить в ф-цию напр понятие каждые 2 месяца очень расплывчато, я через ето прошел даже месяц и то сложно напр депозит на месяц, в рекламках есть, по факту у нас в днях ..... stax ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2016, 20:33:42 |
|
||
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
С подсчетом дней все получилось, спасибо за советы. Теперь еще одно (не)маленькое усложнение. Нужно подсчитать сумму списанной абонплаты за то время, когда услуга была включена в течении указанного периода. Осложнение в том, что абонплата (ее величина и периодичность) определяется в тарифе. А тариф на услуге может изменяться, и дата смены тарифа никак не связана со статусом услуги (а в общем случае она не привязана и к периодичности тарифа, т.е. тариф можно изменять досрочно). То есть у меня есть периодическая таблица со статусом услуги (включена/выключена) и еще одна периодическая таблица с тарифом услуги. У меня пока нет предположений, как эти две несвязанных периодических таблицы "спроецировать" в один запрос. Поэтому я думаю одним запросом выгрузить во временную вспомогательную таблицу с периодами тарифов и величиной абонплаты (таблицу с полями Услуга, АбонплатаЗаСутки, Начало, Конец), а затем вторым запросом посчитать количество дней в периоде, когда услуги были включены, и связать их с первой вспомогательной таблицей для подсчета суммы абонплаты. Не подскажите, можно ли тут все же обойтись без временных таблиц? В крайнем случае устроит VIEW (обычный или материализованный), но хотелось бы обойтись без него. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2016, 21:07:28 |
|
||
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
Alibek B.А тариф на услуге может изменяться, и дата смены тарифа никак не связана со статусом услуги (а в общем случае она не привязана и к периодичности тарифа, т.е. тариф можно изменять досрочно). Поясню. Например в исходном примере у Услуги4 у статуса вообще один период (услуга как включилась, так более и не изменялась), а тариф в этом периоде мог меняться несколько раз. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2016, 21:18:43 |
|
||
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
И в чем проблема? 1. Hаходишь пересечения заданного периода с периoдами включенной услуги. 2. Hаходишь пересечения полученных периодoв с периoдами тарифа 3. Hаходишь "число срабатываний" в каждом периоде и умножаешь на тариф данного периодa. SY. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.09.2016, 22:47:06 |
|
||
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
3. Период, в котором услуга "срабатывает" и период в котором действует тариф — это совершенно разные периоды. По отдельности каждый из них я могу определить. А затем мне нужно перенести эти разные периоды в один совмещенный. Графически это выглядит так: ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.10.2016, 00:00:59 |
|
||
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
Ну так я и сказал - поэтапно. Например задан период: 1/1/2015 - 12/31/2015. Услуга 1 включена: 7/12/2014 - 3/25/2015 5/11/2015 - 7/18/2015 10/10/2015 - 2/28/2016 Тарифы: 7/12/2014 - 1/25/2015 1р 1/26/2015 - 5/15/2015 2p 5/16/2015 - 9/27/2015 3p 9/28/2015 - 2/19/2016 4p Делаем пересeчение заданного периодa и услуга 1 включена. Получаем: 1/1/2015 - 3/25/2015 5/11/2015 - 7/18/2015 10/10/2015 - 12/31/2015 Теперь пересeчение полученных периодов с периoдами таpифа: 1/1/2015 - 1/25/2015 1р 5/11/2015 - 5/15/2015 2p 5/16/2015 - 7/18/2015 3p 10/10/2015 - 12/31/2015 4p Посколько услуга 1 имеет периодичность "Ежедневно", имеем: (1/25/2015 - 1/1/2015 + 1) * 1р + (5/15/2015 - 5/11/2015 + 1) * 2p + (7/18/2015 - 5/16/2015 + 1) * 3p (12/31/2015 - 10/10/2015 + 1) * 4p SY. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.10.2016, 04:18:21 |
|
||
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
Спасибо за пошаговое объяснение, понял идею. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.10.2016, 20:19:17 |
|
||
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
Alibek B.3. Период, в котором услуга "срабатывает" и период в котором действует тариф — это совершенно разные периоды. По отдельности каждый из них я могу определить. А затем мне нужно перенести эти разные периоды в один совмещенный. Графически это выглядит так: Это решатется на уровне реляционной модели представления данных( нормализация отношений). Услуга услугой, а тариф тарифом, это разные сущьности. При изменении тарифа на лету ставится отметка в фактах об изменинии тарифа, но не выключается услуга. Представление данных в БД меняется , но картина мира 19725331 какой была, такой и осталась позрачной и понятной и безнес аналитику и обывателю, который пользуется услугой. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2016, 13:18:30 |
|
||
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
Alibek B.То есть у меня есть периодическая таблица со статусом услуги (включена/выключена) и еще одна периодическая таблица с тарифом услуги. У меня пока нет предположений, как эти две несвязанных периодических таблицы "спроецировать" в один запрос. Поэтому я думаю одним запросом выгрузить во временную вспомогательную таблицу с периодами тарифов и величиной абонплаты (таблицу с полями Услуга, АбонплатаЗаСутки, Начало, Конец), а затем вторым запросом посчитать количество дней в периоде, когда услуги были включены, и связать их с первой вспомогательной таблицей для подсчета суммы абонплаты. Не подскажите, можно ли тут все же обойтись без временных таблиц? В крайнем случае устроит VIEW (обычный или материализованный), но хотелось бы обойтись без него. мне видится left outer join c коррелированным подзапросом. если у вас есть смена тарифа без выключения-включения услуги, то коррелированный подзапрос должен вам вернуть в выборке строки о факте перехода на новый тариф, на основании которого, вы разделите интервал предоставления услуги на несколько интервалов. Смотрите внимательно на планы, индексы и статистику , left outer join с коррелированными подзапросами имею свойство уходить в фулсканы. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2016, 14:00:16 |
|
||
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
д0k , для начала уточню, что бизнес-логика БС реализована вовсе не в БД. БД используется исключительно как хранилище данных. Вся логика реализована программным кодом на сервере приложений и там никаких противоречий с интервалами нет. Попробую еще раз пояснить рисунком. Есть клиенты, у клиентов есть услуги (0, 1 или много). У услуг есть ряд атрибутов, например тариф и статус. Иллюстрация относится к услуге. В данном примере у услуги есть 5 диапазонов, в которых действует один из возможных статусов: - включена: с 1 до 4, с 8 до 16, с 19 и далее - выключена: с 4 до 8, с 16 до 19 Также у услуги есть 5 диапазонов, в которых действует один из тарифов: - тариф 50: с 1 до 6 - тариф 20: с 6 до 10 - тариф 90: с 10 до 14 - тариф 70: с 14 до 20 - тариф 50: с 20 и далее Мне нужно за определенный период (например с 1 по 25) определить стоимость услуги. SY натолкнул меня на мысль и я делаю следующее: 1. Получаю список диапазонов тарифов за указанный период. Это 5 диапазонов: [1-6), [6-10), [10-14), [14-20), [20-26). 2. Получаю список диапазонов включенных статусов за указанный период. Это 3 диапазона: [1-4), [8-16), [19-26). 3. Затем выполняю операцию (логическую) INTERSECT между этими диапазонами и получаю следующие 6 диапазонов: [1-4), [8-10), [10-14), [14-16), [19-20), [20-26). Полученные диапазоны я уже использую для того, чтобы получить значение действующего тарифа на начало каждого диапазона и просуммировав, получить общую стоимость тарифов. У меня получился такой запрос: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. Мне кажется, что это не лучший вариант и такой результат можно получить с помощью MINUS или INTERSECT. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2016, 16:28:42 |
|
||
|
Как посчитать длительность периодов в диапазоне?
|
|||
|---|---|---|---|
|
#18+
Начни с потенциальных дат предоставления услуги: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. SY. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 03.10.2016, 17:35:26 |
|
||
|
|

start [/forum/topic.php?fid=52&msg=39319628&tid=1887333]: |
0ms |
get settings: |
7ms |
get forum list: |
13ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
179ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
64ms |
get tp. blocked users: |
1ms |
| others: | 212ms |
| total: | 491ms |

| 0 / 0 |
