|
Как можно повторно использовать сложный подзапрос без WITH и дублирования?
|
|||
---|---|---|---|
#18+
У меня есть таблица-справочник, в которой есть значения для разных интервалов входных данных и "значение по умолчанию" для входных данных, не относящихся ни к одному интервалу. В табличном виде это выглядит примерно так: shedulenamehour_beghour_endis_systemv1v21По умолчанию00:0024:001......2Остальное время00:0024:001......2Утро06:0010:000......2Вечер18:0022:000...... Мне нужно для разных schedule на определенное время дня получить действующие значения v1, v2 и т.д. При этом, если на определенное время не найдена конкретная запись (с is_system=0), то нужно использовать запись по умолчанию (с is_system=1). Если бы это была готовая таблица, то я бы использовал nvl и два джойна к этой таблице, внутри которых добавлял бы условие по is_system. Но запрос, которым я получаю вышеприведенную таблицу, довольно громоздкий, но использовать WITH я не хочу, потому что его бывает сложно комбинировать с другими WITH и не всегда получается засунуть его в подзапрос. Если использовать подзапросы, то и без того громоздки запрос получается вдвое более громоздким. А с учетом того, что мне в одном запросе нужно получить значения на два момента времени (на текущий момент и на момент 5 минут назад), то запрос учетверяется. Сам запрос, возвращающий интервалы и действующие в этих интервалах данные: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.
BM_SCHEDULE — список различных расписаний, в соответствии с которым определяются интервалы. В столбце BLOCKS_QTY указывается, на сколько частей делятся сутки для данного расписания (если задано 24, значит интервалы могут часовые, если задано 48, значит интервалы могут быть получасовые, если задано 1, значит интервал только один и охватывает сутки целиком). BM_SEGMENT — интервалы группируются в сегменты, в расписании обязательно присутствует один сегмент по умолчанию (IS_SYSTEM=1) и произвольное количество дополнительных сегментов. Например в таблице с примерами для расписания 2 задан один системный сегмент "Остальное время" и два сегмента "Утро" и "Вечер". BM_EXTENT — список интервалов, включенных в сегмент, которые задаются диапазоном. Область действия диапазона интервалов может быть ограничена днем недели, днем месяца, месяцев, годом (таблица BM_DAY_MASK). В информационной системе есть тарифы, у тарифа задано расписание (SCHEDULE_ID) и заданы различные параметры, привязанные в интервалам. Мне нужно найти те тарифы, у которых за последние 5 минут изменились параметры, и определить для них текущие и предыдущие параметры. ... |
|||
:
Нравится:
Не нравится:
|
|||
12.11.2021, 15:34 |
|
Как можно повторно использовать сложный подзапрос без WITH и дублирования?
|
|||
---|---|---|---|
#18+
С WITH получается так: Код: 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. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43.
Результаты правильные, но я бы хотел составить запрос без WITH. Но без него получается очень громоздко. ... |
|||
:
Нравится:
Не нравится:
|
|||
12.11.2021, 16:04 |
|
Как можно повторно использовать сложный подзапрос без WITH и дублирования?
|
|||
---|---|---|---|
#18+
Alibek B. я бы использовал nvl и два джойна к этой таблице, внутри которых добавлял бы условие по is_system. Зачем так извращаться? Воспользуйтесь любым подходящим методом получения top-1. Alibek B. использовать WITH я не хочу, потому что его бывает сложно комбинировать с другими WITH и не всегда получается засунуть его в подзапрос. ??? Вот тут вообще не понял. ... |
|||
:
Нравится:
Не нравится:
|
|||
12.11.2021, 16:42 |
|
Как можно повторно использовать сложный подзапрос без WITH и дублирования?
|
|||
---|---|---|---|
#18+
andrey_anonymous Воспользуйтесь любым подходящим методом получения top-1. Не совсем понял идею. Делать сортировку в подзапросе (order by is_system desc, hour_beg asc) и брать первую запись? По-моему это еще сложнее, чем в моем варианте. andrey_anonymous Вот тут вообще не понял. Мне потом полученную конструкцию нужно будет использовать в более сложном запросе, где уже есть with. Если ее добавлять как подзапрос — with ... select ... from ... (with ... ) cal join ... — то я сталкивался с тем, что такой запрос странно себя ведет, мне не всегда понятно, как он работает. То ли проявляются какие-то баги (версия Oracle 10g), то ли скорее всего я какие-то нюансы не учитываю, но я несколько раз сталкивался со сложностями и стараюсь избегать вложенных with. А если добавлять его в цепочку — with cal as ..., sq1 as ... select ... — то такой запрос сложно сопровождать. ... |
|||
:
Нравится:
Не нравится:
|
|||
12.11.2021, 17:00 |
|
Как можно повторно использовать сложный подзапрос без WITH и дублирования?
|
|||
---|---|---|---|
#18+
Alibek B., Есть такое слово - представление - создается командой create or replace view Любое созданное представление можно использовать в качестве таблицы-источника данных в предложении From Ваш With в вашей версии системы, вы можете привести к форме "параметризованного представления", например, используя sys_context и опираясь на либо именованный, либо на клиентский контекст ('CLIENTCONTEXT') ... |
|||
:
Нравится:
Не нравится:
|
|||
12.11.2021, 17:47 |
|
Как можно повторно использовать сложный подзапрос без WITH и дублирования?
|
|||
---|---|---|---|
#18+
Alibek B. По-моему это еще сложнее, чем в моем варианте. Зато заметно эффективнее в некоторых применениях и уж точно лаконичнее чем двойной join. Попробуйте внимательно изучить http://orasql.org/2012/09/21/distinct-values-by-index-topn/ http://orasql.org/2013/07/05/topn-2/ Alibek B. А если добавлять его в цепочку — with cal as ..., sq1 as ... select ... — то такой запрос сложно сопровождать. Это верное применение with. И сопровождать его совершенно не сложно, если ввести элементарные правила форматирования и совсем чуть-чуть привыкнуть. ... |
|||
:
Нравится:
Не нравится:
|
|||
12.11.2021, 21:02 |
|
Как можно повторно использовать сложный подзапрос без WITH и дублирования?
|
|||
---|---|---|---|
#18+
booby Ваш With в вашей версии системы, вы можете привести к форме "параметризованного представления", например, используя sys_context Звучит интересно, почитаю. Не знал, что так можно. andrey_anonymous Это верное применение with. С форматированием я бы еще справился, но усложняется и отладка запроса. Не получится просто скопировать фрагмент собственно запроса, отладить/скорректировать и вернуть обратно; с запросом нужно копировать и часть with, попутно адаптируя текст запроса. За наводку с TopN спасибо, поизучаю, но выглядит довольно сложно. Сложнее, чем двойной джойн. ... |
|||
:
Нравится:
Не нравится:
|
|||
12.11.2021, 23:09 |
|
Как можно повторно использовать сложный подзапрос без WITH и дублирования?
|
|||
---|---|---|---|
#18+
Alibek B. Не получится просто скопировать фрагмент собственно запроса, отладить/скорректировать и вернуть обратно; с запросом нужно копировать и часть with, попутно адаптируя текст запроса. With - часть запроса, копировать надо весь запрос. Отлаживаться с with сильно легче, поскольку можно отладить по отдельности все представления, не корежа запрос. Особенно оцените когда двинетесь на более свежие версии rdbms, которые не требуют обязательного упоминания в запросе всех веток with. происходит это так: Код: 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. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56.
Надеюсь, идея понятна. Кроме того, в том же pl/sql developer SQL окно позволяет выделить непосредственно тот кусок текста, который надо выполнить, не вырезая его из запроса. Для отладки это не очень удобно, а вот просто глянуть на данные - вполне. Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9.
... |
|||
:
Нравится:
Не нравится:
|
|||
13.11.2021, 11:32 |
|
|
start [/forum/topic.php?fid=52&msg=40111387&tid=1879759]: |
0ms |
get settings: |
16ms |
get forum list: |
5ms |
check forum access: |
1ms |
check topic access: |
1ms |
track hit: |
56ms |
get topic data: |
3ms |
get forum data: |
1ms |
get page messages: |
201ms |
get tp. blocked users: |
0ms |
others: | 378ms |
total: | 662ms |
0 / 0 |