13.10.2016, 16:20 | #1 |
Участник
|
Выбор записей из таблицы произвольным запросом
Добрый день!
Есть задача выбрать из таблицы записи очень сложным запросом с ветвистой логикой, а по выбранным записям делать всевозможные преобразования. Хочется инкапсулировать процедуру поиска строк и потом использовать во всевозможных преобразованиях. Выбираю между (решения по убыванию приоритета предпочитаемости): 1. RecordRefrenceList_RU Минусы - номерные серии, вставка очистка, нельзя использовать в постоянно используемом функционале. 2. RecordSortedList Минусы - дополнительная логика на update и delete строк 3. Временная таблица Минусы - большие временные затраты. Вопрос - может пропустил что? Другие доводы? Axapta 2009 |
|
|
За это сообщение автора поблагодарили: Ace of Database (5), S.Kuskov (5). |
13.10.2016, 16:29 | #2 |
Участник
|
У вас задача как-то нечетко описана.
Непонятно что же именно нужно и как один пункт может заменить другой. Например, как RecordSortedList заменит RecordRefrenceList_RU ? Опишите тогда вашу задачу более детально. |
|
13.10.2016, 16:35 | #3 |
Участник
|
Есть таблица, из нее нужно выбрать по некоторому алгоритму строки.
Если все время писать while select и бороду условий - то это не есть гуд, хочется описать один раз и потом только пользоваться. 1. RecordRefrenceList_RU - заполняем RecordReferenceList_RU делаем join к таблице - работаем с записями 2. Заполняем RecordSortedList перебираем в цикле - работаем с записями 3. Временная таблица - надеюсь понятно |
|
13.10.2016, 16:55 | #4 |
Administrator
|
Цитата:
Почему нельзя использовать в постоянно используемом функционале? Там неправильно хранить записи, но добавить их туда с перспективой удаления - почему бы и нет. Если все-таки хочется хранить ссылки, то всегда можно создать свою таблицу, аналогичную RecordReferenceList_RU (точнее пару таблиц - шапку и строки сессии выборки данных). Работает все быстро, памяти не кушает - все удобно. Впоследствии хорошо фильтровать данные, а также выводить отфильтрованные данные в привычной форме (например, можно т.о. собрать список номенклатур и открыть стандартную форму номенклатур, отфильтрованную по джойну с вашей таблицей ссылок. Или т.о. отобрать складские проводки). Цитата:
А также - расход места на диске, который скорее всего не предназначен для хранения данных БД и увеличение времени выборки за счет отсутствия каких-либо индексов. В общем - используйте RecordReferenceList_RU и не мучайтесь
__________________
Возможно сделать все. Вопрос времени |
|
|
За это сообщение автора поблагодарили: NetBus (2). |
13.10.2016, 17:08 | #5 |
Участник
|
Цитата:
Сообщение от NetBus
Если все время писать while select и бороду условий - то это не есть гуд, хочется описать один раз и потом только пользоваться.
1. RecordRefrenceList_RU - заполняем RecordReferenceList_RU делаем join к таблице - работаем с записями 2. Заполняем RecordSortedList перебираем в цикле - работаем с записями 3. Временная таблица - надеюсь понятно дело в том, что ядро аксапты ооочень много кэширует. изначально таблицы в Аксапте очень четко делились на параметры/справочники/документы/проводки параметры содержат только одну запись для каждой компании справочники редко редактируются, но часто читаются документы - в основном произвольный доступ в ручном режиме, очень редки bulk операции проводки - только добавляются, никогда не удаляются и в очень исключительных ситуациях редактируются (корреспонденция, к сожалению, - антипаттерн) это со стороны ядра Аксапты. со стороны SQL есть кэширование планов запросов/статистики и прочее техническое кэширование. в SQL в многопользовательском режиме лучше отправлять не уникальные разные запросы с кучей join, а поток стандартизированных сравнительно простых запросов. таким образом - уникальные select с бородой запросов - это плохой подход в большинстве случаев. Да, есть случаи когда один-два-три сложных запросов лучше, чем куча простых запросов. Но в большинстве своем лучше стремиться к стандартизированным запросам, полученные результаты которых может быть дополнительно обрабатываются уже в классе. Исходя из этого в Аксапте и сложился стиль - бизнес-логика почти не занимается такими низкоуровенвыми вещами как запросы. бизнес-логика должна вызывать классы, которые в свою очередь будут делать относительно простые и стандартизированные запросы к базе. да, люди которые привыкли напрямую работать с SQL, часто морщатся от такого подхода. да, в аксапте иногда очень не хватает union, having и вложенных запросов. да, иногда приходится юзать ResultSet см. https://github.com/mazzy-ax/SysResultSet а также комментарии в https://github.com/mazzy-ax/SysResul...sultSet_AX.xpo но в большинстве случаев лучше и эффективнее пользоваться логическим разбиением на слои: 1. бизнес-логика обращается к специализированным классам 2. специализированные классы делают относительно простые запросы и/или обращаются к другим классам. в большинстве случаев не пытайтесь сделать монстр-запрос. лучше обычные циклы, которые вызывают методы классов. во-первых, монстр-запрос это преждевременная оптимизация ) во-вторых, во многих случаях в многопользовательской системе монстр-запрос будет работать хуже и будет дороже в обслуживании. ========================= и уж точно не занимайтесь RecordSortedList и RecordRefrenceList_RU, если у вас не стоит явная задача именно оптимизации производительности данного конкретного участка. ========================= временные таблицы можно использовать когда вы точно знаете, что вам нужен промежуточный результат, И объем этого результата в разы, на порядки меньше, чем объем исходных данных. вопрос временных таблиц оооочень сильно зависит от версии системы. не закладывайтесь на временные таблицы только из соображений производительности. скорее всего, вы ничего не выиграете. особенно для "произвольных запросов". Последний раз редактировалось mazzy; 13.10.2016 в 17:44. |
|
|
За это сообщение автора поблагодарили: NetBus (2), alex55 (1), dech (3). |
13.10.2016, 17:15 | #6 |
Участник
|
Цитата:
вопрос опять о "произвольных запросах" и о сферических конях в вакууме типа "выбрать из таблицы". (из одной, карл!) для Аксапты, для прикладной программы уровня предприятия "произвольные запросы" - предельно редкое явление. встречающееся на уровне программирования ядра и функционала администрирования. запрос к ОДНОЙ таблице - встречается как правило только на этапе отладки или как запрос параметров (но для параметров точно нужно использовать find()). запрос к одной таблице, которая не является параметрами - редкое явление. а в версии 2012 и выше с искусственными ключами - исключительное явление. для Аксапты характерно очень прикладное программирование. для прикладного программирования "работать напрямую с таблицей" - антипаттерн. в прикладной программе типа аксапты обычно работают с набором взаимосвязанных таблиц!!!! работать с набором взаимосвязанных таблиц напрямую? нонсенс! Последний раз редактировалось mazzy; 13.10.2016 в 17:30. |
|
13.10.2016, 17:34 | #7 |
Участник
|
особенно, если в наборе есть таблицы, для которых включен Valid Time State
https://msdn.microsoft.com/en-us/library/gg861781.aspx |
|
13.10.2016, 18:06 | #8 |
Участник
|
Всем спасибо за участие!
Познавательно, вспомнил еще способ 5. macros а ля InventDimJoin как в складском модуле. Выбирай на любой вкус... ушел думать |
|
13.10.2016, 18:45 | #9 |
Участник
|
|
|
13.10.2016, 18:53 | #10 |
Участник
|
|
|
13.10.2016, 20:25 | #11 |
Administrator
|
Цитата:
Цитата:
Сообщение от mazzy
Оп! Категорически не согласен!
вопрос опять о "произвольных запросах" и о сферических конях в вакууме типа "выбрать из таблицы". (из одной, карл!) для Аксапты, для прикладной программы уровня предприятия "произвольные запросы" - предельно редкое явление. встречающееся на уровне программирования ядра и функционала администрирования. для Аксапты характерно очень прикладное программирование. для прикладного программирования "работать напрямую с таблицей" - антипаттерн. в прикладной программе типа аксапты обычно работают с набором взаимосвязанных таблиц!!!! работать с набором взаимосвязанных таблиц напрямую? нонсенс! Цитата:
Сообщение от mazzy
особенно, если в наборе есть таблицы, для которых включен Valid Time State
https://msdn.microsoft.com/en-us/library/gg861781.aspx Итак, задача 1 Из этой задачи следует, что нужно выбрать из одной (да-да, из одной!) таблицы. В этом случае класс RecordReferenceList_RU очень хорошо помогает. Про прикладное программирование - хорошее замечание. Но... вопрос не ставился как "работать ли напрямую с таблицей или использовать промежуточный класс?". Автор как раз хотел использовать класс, а я ему советовал так не делать. Тут я был неправ, но хочу сказать, что без модификаций класса RecordReferenceList_RU его использовать будет не очень удобно - тогда действительно придется связываться с номерными сериями. Резюме: класс нужен, но не совсем такой, какой есть в штатной поставке. По поводу набора таблиц. Начиная с АХ 2012 и выше - надо будет помнить, что "простейший" справочник типа клиентов / номенклатуры и т.д. состоит не из одной таблицы, а из набора таблиц, связанных друг с другом и в данном случае ссылкой на одну запись в одной таблице можно не обойтись. Однако, автор указывает, что версия как раз АХ 2009, в которой еще многие справочники состоят из одной таблицы и поэтому решение предлагается именно для этой версии. Для версии АХ 2012 оно (решение) было бы другим. Соответственно таблиц, для которых включен Valid Time State в АХ 2009 нет и об этом в АХ 2009 не надо заморачиваться. Теперь задача 2 Цитата:
Т.о. если Вам надо: - выбрать произвольным образом записи из ОДНОЙ таблицы для ИСКЛЮЧИТЕЛЬНО целей дальнейшей фильтрации и / или отображения по ним - то можно использовать RecordReferenceList_RU - выбрать произвольным образом записи из одной или нескольких таблиц и в последующем их как-то обрабатывать "всевозможными преобразованиями", то нужно писать find-ы и делать логику в семействе классов (т.е. создавать ряд классов, занимающихся обработкой и поиском; выносить общий код в классы-родители и т.д.)
__________________
Возможно сделать все. Вопрос времени |
|
13.10.2016, 20:56 | #12 |
Участник
|
Цитата:
Сообщение от sukhanchik
Т.о. если Вам надо:
- выбрать произвольным образом записи из ОДНОЙ таблицы для ИСКЛЮЧИТЕЛЬНО целей дальнейшей фильтрации и / или отображения по ним - то можно использовать RecordReferenceList_RU - выбрать произвольным образом записи из одной или нескольких таблиц и в последующем их как-то обрабатывать "всевозможными преобразованиями", то нужно писать find-ы и делать логику в семействе классов (т.е. создавать ряд классов, занимающихся обработкой и поиском; выносить общий код в классы-родители и т.д.) ===================== Давай ))) тема: Выбор записей из таблицы произвольным запросом Цитата:
Цитата:
да, я тоже обратил внимание на единственное число. но подумал, что люди хотят не то, что спрашивают, и срашивают не то, что хотят. как обычно. ) но если предположить твою трактовку: а какой запрос по какой таблице аксапты ты бы назвал подходящим под определение "сложная и ветвистая логика запроса по одной таблице"? просто интересно. Цитата:
Сообщение от sukhanchik
В этом случае класс RecordReferenceList_RU очень хорошо помогает. Про прикладное программирование - хорошее замечание. Но... вопрос не ставился как "работать ли напрямую с таблицей или использовать промежуточный класс?". Автор как раз хотел использовать класс, а я ему советовал так не делать. Тут я был неправ, но хочу сказать, что без модификаций класса RecordReferenceList_RU его использовать будет не очень удобно - тогда действительно придется связываться с номерными сериями. Резюме: класс нужен, но не совсем такой, какой есть в штатной поставке.
а что ты имеешь в виду? что должно быть в таком классе? и чем это будет лучше чем набор отдельных запросов в сложной и ветвистой логике? Цитата:
да, ну, брось... я понимаю еще таблицу с проводками. в результате надо получить дебет-кредит с учетом сторно и какие-нибудь хитрые группировки. но группировки по одной таблице проводок, не заглядывая в справочники? а сложную и ветвистую логику для справочника из одной таблицы? дерево что ли? и что там сложного? в общем, не понимаю. Цитата:
читают то многие. а вопрос неплохой вроде. Цитата:
то может и не заморачиваться с "произвольным запросом" а сразу сделать нормальные классы? )))) |
|
13.10.2016, 21:15 | #13 |
Administrator
|
Цитата:
Цитата:
В свое время (АХ 4.0) у меня была задача поиска "закольцованных" движений. Соответственно, чтобы понять "кольцо" - нужно для каждой записи (каждого типа движения) применить свой алгоритм обработки. На выходе может получиться неопределенно много записей и тривиальный фильтр не подходит, соответственно ссылку на RecId найденных записей было удобно записывать в RecordReference_RU, а затем открывать стандартную форму InventTrans, отфильтрованную по отобранным движениям. Цитата:
да, я как-то незаметно стал ассоциировать "одну таблицу" со справочником. Каюсь. Цитата:
а) использовать что-то типа InventTrans, из которого еще не выкосили "лишние" поля б) сознательно денормализовать нормализованные Микрософтом таблицы для ускорения выборок. Цитата:
Цитата:
ну тут не поспоришь - конечно надо делать нормальные классы.
__________________
Возможно сделать все. Вопрос времени |
|
|
За это сообщение автора поблагодарили: mazzy (2). |
13.10.2016, 21:22 | #14 |
Administrator
|
Альтернативный вариант - немного поменять взгляд на задачу. Вместо того, чтобы возвращать записи, упаковкнные в какой-то контейнер, можно возвращать сформированный запрос. Например, в виде объекта Query или QueryRun. Если возвращаемая таблица во всех вариантах запроса одна, то можно инициализировать табличный курсор с помощью select noFetch и вернуть его.
__________________
Not registered yet? Register here! Have comments, questions, suggestions or anything else regarding our web site? Don't hesitate, send them to me |
|
|
За это сообщение автора поблагодарили: mazzy (2), NetBus (2). |
13.10.2016, 21:30 | #15 |
Administrator
|
Цитата:
Union в Аксапте есть: https://msdn.microsoft.com/en-us/library/cc605991.aspx Having и вложенные запросы можно эмулировать через промежуточные View.
__________________
Not registered yet? Register here! Have comments, questions, suggestions or anything else regarding our web site? Don't hesitate, send them to me |
|
|
За это сообщение автора поблагодарили: mazzy (2). |
13.10.2016, 21:35 | #16 |
Участник
|
Цитата:
Сообщение от sukhanchik
InventTrans В свое время (АХ 4.0) у меня была задача поиска "закольцованных" движений. Соответственно, чтобы понять "кольцо" - нужно для каждой записи (каждого типа движения) применить свой алгоритм обработки. На выходе может получиться неопределенно много записей и тривиальный фильтр не подходит, соответственно ссылку на RecId найденных записей было удобно записывать в RecordReference_RU, а затем открывать стандартную форму InventTrans, отфильтрованную по отобранным движениям. . |
|
13.10.2016, 21:36 | #17 |
Administrator
|
Посмотрите для примера на класс TradeLoopTrans. Пример его использования - метод CustInvoiceJour.queryCustInvoiceTrans и отчёт SalesInvoice метод fetch. Если я правильно понял вашу задачу, то в стандартных отчётах-документах по заказу/закупке реализовано нечто похожее.
__________________
Not registered yet? Register here! Have comments, questions, suggestions or anything else regarding our web site? Don't hesitate, send them to me |
|
13.10.2016, 21:42 | #18 |
Участник
|
Ветвистая логика может означать, что при разных входных параметрах нужно использовать разные по сути запросы. Сами запросы могут быть и не всегда сложные. Вопрос в том чтобы отделить и инкапсулировать первичный отбор от последующей обработки.
Более общая формулировка задачи: Как (с минимальными накладными затратами) результат (выход) одного алгоритма подать на вход следующего, так что бы алгоритмы не зависили от тонкостей реализации друг друга. Общего рецепта по-видимому нет. Когда-то будут более выгодны временные таблицы, когда-то квазивременные |
|
13.10.2016, 21:45 | #19 |
Участник
|
Цитата:
Сообщение от Maxim Gorbunov
Альтернативный вариант - немного поменять взгляд на задачу. Вместо того, чтобы возвращать записи, упаковкнные в какой-то контейнер, можно возвращать сформированный запрос. Например, в виде объекта Query или QueryRun. Если возвращаемая таблица во всех вариантах запроса одна, то можно инициализировать табличный курсор с помощью select noFetch и вернуть его.
|
|
|
За это сообщение автора поблагодарили: mazzy (2). |
13.10.2016, 22:00 | #20 |
Участник
|
Цитата:
Цитата:
Сообщение от sukhanchik
InventTrans
В свое время (АХ 4.0) у меня была задача поиска "закольцованных" движений. Соответственно, чтобы понять "кольцо" - нужно для каждой записи (каждого типа движения) применить свой алгоритм обработки. На выходе может получиться неопределенно много записей и тривиальный фильтр не подходит, соответственно ссылку на RecId найденных записей было удобно записывать в RecordReference_RU, а затем открывать стандартную форму InventTrans, отфильтрованную по отобранным движениям. или ты лот возврата имеешь в виду. а как у него кольцо может образоваться? Цитата:
в результате получить отдельно дебетовые и кредитовые обороты в одном запросе по одной таблице становится проблематично. хотя если можно использовать больше одного датасорса по одной таблице... ))) Цитата:
Сообщение от S.Kuskov
Более общая формулировка задачи:
Как (с минимальными накладными затратами) результат (выход) одного алгоритма подать на вход следующего, так что бы алгоритмы не зависили от тонкостей реализации друг друга. Общего рецепта по-видимому нет. Когда-то будут более выгодны временные таблицы, когда-то квазивременные Один класс инкапсюлирует одно, другой класс - другое. они могут использовать друг-друга. тут вопрос оптимальности и нагрузки на базу. очень многие люди считают, что один монстр-запрос будет работать оптимальнее. поэтому не разбивают на классы. но надо оптимизировать не запрос. а систему в целом. которая работает в многопользовательском режиме. если рассматривать систему в целом, то монстр-запросы как правило очень плохо влияют на среднюю отзывчивость сервера и среднюю производительность. в среднем лучше на SQL подавать несложные и однотипные запросы. даже если при этом получаются не самые минимальные resultSet'ы. |
|
Теги |
distinct, recordrefrencelist_ru, recordsortedlist, view |
|
|