|
Представление иерархии
|
|||
---|---|---|---|
#18+
Добрый вечер, Ваяю представление для удобного доступа к иерархии/графу документов, чтобы меньше писать индивидуальных джойнов. Основано на запросе такого толка, который уже работает как следует. :id содержит номер одного из документов графа. Настоящий запрос сложнее, т.к. содержит несколько подчиненных связочных таблиц. Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
Критерий поиска (where) срабатывает, т.к. doc_id разных типов документов имеют сплошную нумерацию. При поиске фиксируется один документ поиска, и находятся все сопутствующие документы других типов графа. Тут бы пригодились параметризованные представления, но Оракл таких пока не придумал, поэтому придется без них. Можно в представление поместить все до "where", и тогда в каждом запросе придется добавлять это многострочье, которое со временем будет расти. Эмуляции параметризованного представления через глобальную переменную или таблицо-функцию не устраивают. А можно как-то в представление засунуть список поисковых полей? Что-то вроде такого: Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
... |
|||
:
Нравится:
Не нравится:
|
|||
31.10.2020, 03:33 |
|
Представление иерархии
|
|||
---|---|---|---|
#18+
Померял время исполнения; этот многострочник учетверяет время запроса до секунды-двух, т.к. оптимизатор не знает что они взаимоисключающие. вместо Код: plsql 1. 2. 3. 4. 5.
будет значительно быстрее определить тип дока по :id, а затем свернуть до одного условия поиска. Если бы у графа был корень он был бы дедушкой, можно было бы свести к корню, и строить иерархию от него. ... |
|||
:
Нравится:
Не нравится:
|
|||
31.10.2020, 04:27 |
|
Представление иерархии
|
|||
---|---|---|---|
#18+
А ты уверен, что правильно понимаешь как работает конструкция Код: plsql 1. 2. 3. 4. 5. 6.
... |
|||
:
Нравится:
Не нравится:
|
|||
31.10.2020, 07:49 |
|
Представление иерархии
|
|||
---|---|---|---|
#18+
Вячеслав Любомудров А ты уверен, что правильно понимаешь как работает конструкция Код: plsql 1. 2. 3. 4. 5. 6.
Вроде бы да, я не задумывался особо когда писал. А что, какая-то часть показалась необычной? Orders-jobs содержит две колонки. В первой (order_id) всегда id заказа, во второй всегда id документа который не заказ, но с заказом связан. Не для всех заказов есть строка в этой таблице. PK = (order_id,doc_id). ... |
|||
:
Нравится:
Не нравится:
|
|||
31.10.2020, 08:16 |
|
Представление иерархии
|
|||
---|---|---|---|
#18+
Вот и надо это всегда/невсегда правильно оформлять И, возможно, юзать скобки -- пока оно выполняется последовательно и видеть INNER JOIN после OUTER JOIN без изменения порядка скобками часто похоже на ошибку Код: 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.
Ты ожидал именно такого результата? ... |
|||
:
Нравится:
Не нравится:
|
|||
31.10.2020, 08:27 |
|
Представление иерархии
|
|||
---|---|---|---|
#18+
Вячеслав Любомудров, Вы правы, пример жёлтым скроет заказ, у заказа есть активности, но только типов не включенных в запрос (напр, только акваланг, которого в запросе нет). Левый джойн приносит много разных типов документов (в примере-занятий). В более общем случае пример иерархии такой: Код: plaintext 1. 2. 3. 4. 5.
Если заказ одинокий (не имеет подчинённых документов, то его все равно нужно показать, хотя строки в связке нет. Исходя из этого я сделал левый джойн. Среди всех занятий в бд меня интересуют не все,поэтому я использовал внутренний джойн чтобы исключить ненужные. А если все - ненужные, то пропадает сам заказ. Проблема. Если я сначала сделаю inner join таблицы связок с активностями, а потом outer с заказами, то должно быть правильно. Вот только как это делать скобками я не знаю, знаю через вложенный селект. Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
... |
|||
:
Нравится:
Не нравится:
|
|||
31.10.2020, 09:12 |
|
Представление иерархии
|
|||
---|---|---|---|
#18+
Я не разработчик и что-то советовать именно по алгоритму вряд ли смогу (лениво) Но вот употреблять правильную терминологию посоветовать могу -- иерархия -- эьто таки [практически однокорневое] дерево с более чем одним уровнем наследования Это использование специальных "иеархических" запросов, использующих, как правило, классический CONNECT BY или новомодный Recursive Subquery Factoring (через with) А у тебя, насколько я могу навскидку увидеть -- сплошной OUTER JOIN, только надо правильно расставить приоритеты -- кто однозначно есть, а кого может и не быть ... |
|||
:
Нравится:
Не нравится:
|
|||
31.10.2020, 09:24 |
|
Представление иерархии
|
|||
---|---|---|---|
#18+
Код: plsql 1. 2. 3. 4. 5.
Такой вариант не устраивает, т.к. добавляет лишние строки в мой отчёт. Поскольку заказы наверху иерархии (создаются первыми), и должны всегда быть показаны, я думаю нужно к ним делать left join всей остальной иерархии,и больше ничего что могло бы спрятать строчку ... |
|||
:
Нравится:
Не нравится:
|
|||
31.10.2020, 09:24 |
|
Представление иерархии
|
|||
---|---|---|---|
#18+
Перестаем называть член пиписькой и начинаем лечить сифилис (с) ... |
|||
:
Нравится:
Не нравится:
|
|||
31.10.2020, 09:27 |
|
Представление иерархии
|
|||
---|---|---|---|
#18+
Вячеслав Любомудров Я не разработчик и что-то советовать именно по алгоритму вряд ли смогу (лениво) Но вот употреблять правильную терминологию посоветовать могу -- иерархия -- эьто таки [практически однокорневое] дерево с более чем одним уровнем наследования Это использование специальных "иеархических" запросов, использующих, как правило, классический CONNECT BY или новомодный Recursive Subquery Factoring (через with) А у тебя, насколько я могу навскидку увидеть -- сплошной OUTER JOIN, только надо правильно расставить приоритеты -- кто однозначно есть, а кого может и не быть У меня фиксированное число уровней, не более 10 (в примере показаны первые два). Это не похоже на дерево переменной глубины и там действительно только джойны и нужны. >А у тебя, насколько я могу навскидку увидеть -- сплошной OUTER JOIN, только надо правильно расставить приоритеты -- кто однозначно есть, а кого может и не быть Однозначно есть только верхний уровень. Второй показан в примере,и вроде разобрались. Ещё могут дочерние уровни от активностей и от связок, там получится outer join для прямых наследников,или ещё одна вложенная конструкция для наследников через таблицы связки. Плюс есть полно мест в этом запросе где просятся inner join т.к. присутствие значений гарантируется внешними ключами. В связи с этим вопрос: если ссылочная целостность обеспечивает одинаковый результат для inner и outer, есть ли предпочтение?помню что в синхронных мат представлениях есть предпочтение в пользу inner, про другие ситуации не знаю. ... |
|||
:
Нравится:
Не нравится:
|
|||
31.10.2020, 09:44 |
|
Представление иерархии
|
|||
---|---|---|---|
#18+
Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
... |
|||
:
Нравится:
Не нравится:
|
|||
31.10.2020, 09:45 |
|
Представление иерархии
|
|||
---|---|---|---|
#18+
Alibek B. Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
Спасибо, я с утра прочитаю и испробую. ... |
|||
:
Нравится:
Не нравится:
|
|||
31.10.2020, 09:49 |
|
Представление иерархии
|
|||
---|---|---|---|
#18+
Утро вечера явно мудренее. Весь сыр-бор с левым джойном к заказам помогал предохранить одинокие заказы, которые не участвовали ни в одной из таблиц связок. Вместо того чтобы их пытаться предохранить усложненными запросами, почему их просто не добавить в конце, раз они такие особые? Вместо начального плана (с ошибкой, указанной Вячеславом) Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
Сделать Код: plsql 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.
Основная идея - вместо того, чтобы начинать с вершины иерархии и сохранять ветки без листьев от пропажи, строить снизу, наслаивая ветки внешними джойнами. Вне SQL, обработка дерева снизу вверх редко практикуется (построение дерева Хоффмана - единственное где такое припоминаю), я даже не подумал что так можно было сделать. ... |
|||
:
Нравится:
Не нравится:
|
|||
31.10.2020, 22:27 |
|
Представление иерархии
|
|||
---|---|---|---|
#18+
Alibek B., я только сейчас заметил что код использует несколько :id1, id2, ... У меня критерий поиска - единственный :id, который соответствует существующему документу одного из известных типов. Нумерация документов всех типов сплошная, поэтому :id можно сравнивать с чем угодно, не проверяя тип. Похоже, я выкрутился, "передав" параметр в представление, добавив колонку всех возможных значений :id. Теперь вместо Код: plsql 1. 2. 3. 4. 5. 6.
я пишу Код: plsql 1.
... |
|||
:
Нравится:
Не нравится:
|
|||
31.10.2020, 22:40 |
|
Представление иерархии
|
|||
---|---|---|---|
#18+
Я читаю, что параметризованные представления - самая затребованая фича для Оракла, но так пока и не сделана. Учитывая, что эту фичу можно без великого труда сделать через глобальные переменные, есть ли причины которые не позволяют Ораклу выбрать синтакс и соорудить такую штуку? Табличные функции или курсоры с параметром это все же не совсем то. ... |
|||
:
Нравится:
Не нравится:
|
|||
01.11.2020, 00:37 |
|
Представление иерархии
|
|||
---|---|---|---|
#18+
Код: plsql 1. 2. 3. 4.
1) Здесь могло бы быть полезным, если бы ORDERS_JOBS "знал", где искать детали, что-то вроде: Код: plsql 1. 2. 3. 4.
2) поищи по форуму "секционирование для бедных" и ознакомьтесь с "partitioned view" где-то здесь: https://docs.oracle.com/cd/A57673_01/DOC/server/doc/A48506/partview.htm оно для похожих на ваш случай историй хорошо подходит. ... |
|||
:
Нравится:
Не нравится:
|
|||
01.11.2020, 05:42 |
|
Представление иерархии
|
|||
---|---|---|---|
#18+
booby, Спасибо за комментарий. 1) doc_id индексирования во всех таблицах, и джойны выглядят довольно эффективно в плане. Таблицы s,w,c являются вью-расширениями одной таблицы DOCS, поэтому это все эффективно идентичные селф-джойны с фильтрацией по полю типа. Т.е. Код: plsql 1. 2. 3. 4.
Но я понял общую идею, что каждый из джойнов был бы короче, и быстрее. В фильтре where, я думал что можно ускорить поиск, вычислив единожды тип параметра, и не делая лишние сравнения "or". Попробовал, та же скорость и практически тот же план, по той же причине что выше. Сейчас запрос исполняется за 0.1-0.2 секунды,и отчёт выскакивает за секунду, что возможно даже слишком быстро - почти не виден красивый прогресс бар. 2) я почитал про partitioning, эт все же для баз данн на пару порядков превышающих мою. У нас все таблицы заметно меньше миллиона строк, и большинство меньше десяти колонок. Но сколько связок! Простой запрос может использовать 20-30 джойнов, если считать скрытые. Структура данных в виде сложного графа представленная в табличном виде это интересно. Например, нашел несколько вспомогательных связующих таблиц которые расширяют основные связующие таблицы. И любопытно что тот, кто это все написал не забыл везде проставить составные внешние ключи. Ковыряться в таком коде - как кроссворды решать. Со временем все сходится и наступает иллюзия полного понимания. ... |
|||
:
Нравится:
Не нравится:
|
|||
01.11.2020, 06:39 |
|
Представление иерархии
|
|||
---|---|---|---|
#18+
НеофитSQL, Похоже, вы опять не поняли. Дело не в количестве строчек, а в способе смотреть на них вам, почти наверно, не нужен и, почти наверно вреден Код: plsql 1. 2. 3. 4.
Нужен вам Код: plsql 1. 2. 3. 4. 5.
с соответствующим случаю оформленным списком выбора. и, скорее всего, она у вас уже есть, просто вы её "не увидели". ... |
|||
:
Нравится:
Не нравится:
|
|||
01.11.2020, 07:38 |
|
Представление иерархии
|
|||
---|---|---|---|
#18+
booby, Union в одну колонку мне не подходит по нескольким причинам, - вьюхи активностей разные - заказчик их хочет видеть на одной строчке в отчёте - к каждому типу активности привязаны свои подчиненные таблицы и операции - union у меня уже есть, в виде правой колонки ORDERS_JOBS Этот запрос (теперь уже представление) является костяком для нескольких отчётов, и многих будущих. Теперь, когда я уже закончил, мне наверное проще будет объяснить что я хотел достичь. В моей бд есть крепкозапутанные зависимости между документами разного типа. Вместо того чтобы для каждой новой задачи чесать репу и вспоминать как прыгнуть от акваланга к Пете, или от Маши к ледорубу, я решил один раз написать универсальное представление которому даёшь один документ, и он притаскивает все зависимые сверху, снизу и сбоку. Где нужно, вернуть несколько строчек. Начиналась как функция (старые привычки быстро не умирают) но переделал на sql. Теперь я просто пишу select * from DOCSPILE_V where Document = :id Вьюха сама определяет тип переданного объекта, и достраивает все сопутствующие. Например, если :id это Петя, добавит его заказы, статус заказов, инвойсы и статус оплаты. Если :id это заказ, то вытащит клиентов (Вася и маша заказывали вместе), инвойс этого заказа и т.д. Если :id это инвойс, то вытащит заказ(ы) и занятия связанные с этим инвойсом, также имена людей фигурирующих в заказе/заказах. Вьюха гарантирует присутствие в отчёте как минимум одной строки, если ей передают существующий :id любого типа. Т.е. если Вася есть в системе, но ничего не заказывал, то вызов представления с :id Васи даст одну строку. Вася будет упомянут, но все другие колонки будут пустые. А вот у заказа будет минимум две заполненных колонки (нужен Гена, чтоб заказ сделать). У инвойса - ещё больше, т.к. ему предшествует создание других документов. Вызов этой вьюхи без параметров выплюнет все документы, с указанием их связей между собой. Слово "параметр" используется вольно. Представления в Оракле не умеют принимать параметры, но для моего узкого случая конечного числа параметров у меня получилось это сделать без внешних переменных. ... |
|||
:
Нравится:
Не нравится:
|
|||
01.11.2020, 08:50 |
|
Представление иерархии
|
|||
---|---|---|---|
#18+
1. При работе со сквозным идентификатором поддержу booby - вариант union ALL c последующей группировкой часто более выгоден, нежели чем хитровыписанный join. 2. В означенной ситуации напрасно отказались от варианта с функцией. Конкретно - от варианта pipelined function, который с точки зрения интерфейса суть искомое параметризованное представление. ... |
|||
:
Нравится:
Не нравится:
|
|||
01.11.2020, 12:55 |
|
Представление иерархии
|
|||
---|---|---|---|
#18+
НеофитSQL, если собрать собрать все, что вы понаписали в топике, то получится, что вы работу нескольких различных задач хотите обеспечить единственным универсальным интерфейсом. В случае обычных языков программирования, это называют библиотечным классом с широким интерфейсом. Вот вам тыр-пыр-лист, а уж там как со стеком вы с ним будете обходиться, или как с очередью, или просто как с массивом - это зависит от того, сумели вы, или нет, выделить правильное подмножество методов из тыр-пыр-листа (и не факт, что он хоть какой-нибудь из предполагаемых вариантов использования, реализация такого широкого интерфейса обеспечивает хорошо). Библиотеко-писатель считает, что он отдаёт пользователю баян, и главное в нём - клавиши, какую комбинацию нажал, такая музыка и польётся. Это ошибка. Главное в гармони не клавиши, а меха. Их сжимать и разжимать надо, чтобы музыка играла. Так, например, бывают устроены политические системы, пар в которых надо периодически сжимать и разжимать, чтобы музыка государственности играла без долговременного затихания. Oracle, это не гармонь, и даже не орган - у органа один конец трубы свободно открытый. Oracle - это сверхдлинный блок цилиндров, в которых находится пар, сверху закрытый поршнями, и удерживаются они только вашей личной силой. А расширяться этот пар в объеме легко может на 4-5 порядков. Общая задача конструкции - молчать. Если услышали звук, значит в свисток уходят ваши усилия по удержанию поршня, а пар продолжает расширяться. Мораль из этого такая: - не стремитесь к ширизне и универсальности интерфейсов. - читайте andrey_anonymous и думайте над тем, что он пишет. И да, поджать парок на 4-5 порядков - это больше для показательного кино на ютубе, но в диапазоне от .75 до 7500 - это совершенно обыденные рабочие варианты на рутинной основе. К этому тоже надо быть морально готовым. Конечно можно и так - сначала написать именно ваш джойн, а потом разложить его на union all, и доложить о достигнутых результатах. Но со временем, в норме, это должно становиться скучным. ... |
|||
:
Нравится:
Не нравится:
|
|||
01.11.2020, 16:38 |
|
Представление иерархии
|
|||
---|---|---|---|
#18+
andrey_anonymous 1. При работе со сквозным идентификатором поддержу booby - вариант union ALL c последующей группировкой часто более выгоден, нежели чем хитровыписанный join. 2. В означенной ситуации напрасно отказались от варианта с функцией. Конкретно - от варианта pipelined function, который с точки зрения интерфейса суть искомое параметризованное представление. Шестиуровневая иерархия, в примере показаны два уровня. Union обрек бы меня на написание шести разных запросов, в зависимости от типа параметра поиска. Как раз этого я не хотел - писать полуповторяющийся код. Согласен что функцию было бы намного легче писать,да и читать. Функция (пайплайн) была на 80% закончена, когда я заметил что у меня всего два if, и я не полагаюсь на библиотечные функции. Поскольку функции я писать умею, а сложные (не то же самое что длинные) запросы в SQL это для меня редкая возможность, я переделал на SQL. В моем случае, функция эффективно может заменить SQL, т.к.результат содержит от десятка до сотни строк для любого значения параметра. В более общем случае, функция является забором для оптимизатора. ... |
|||
:
Нравится:
Не нравится:
|
|||
01.11.2020, 17:36 |
|
Представление иерархии
|
|||
---|---|---|---|
#18+
Снова бредовая постановка и бредовые выводы ... ты эту тему зачем создал? ... |
|||
:
Нравится:
Не нравится:
|
|||
01.11.2020, 17:50 |
|
Представление иерархии
|
|||
---|---|---|---|
#18+
booby, Мне понравилась ваша аналогия с паровой машиной, но по прежнему непонятно желание использовать union. Идея интерфейса который делает "все" меня не прельщает, это противоречит принципу strong cohesion, которому я стараюсь следовать. В то же время, я начал видеть появление запросов "найти все документы по клиенту", "найти все документы по заказу", "найти все документы по инвойсу" которые следовали похожей логике, но повторяли код. Одно из качеств SQL, которое я не встречал в процедурных языках, это способность оптимизатора выкинуть неиспользуемый код следуя внешним фильтрам. Это как если бы функция возвращающая несколько значений заметила бы что я не использую второе и третье, и не стала бы их вычислять. Очень эффективно! Вот придумал пример, который простой и синтетический, но похож на задачу которую я решил. Задача: распечатать все натуральные числа меньше миллиона зная значение и позицию одной из цифр. Параметры: цифра (0-9), ее позиция (0-5). Числа должны следовать критериям: - делиться на семь - делиться на 13 - сумма цифр четная - все цифры разные Я знаю как такую задачку решить через джойны и фильтры, но не знаю, как тут применить юнион. ... |
|||
:
Нравится:
Не нравится:
|
|||
01.11.2020, 18:24 |
|
|
start [/forum/topic.php?fid=52&fpage=33&tid=1880747]: |
0ms |
get settings: |
9ms |
get forum list: |
12ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
46ms |
get topic data: |
12ms |
get forum data: |
3ms |
get page messages: |
63ms |
get tp. blocked users: |
2ms |
others: | 298ms |
total: | 451ms |
0 / 0 |