Участник
Регистрация: 28.11.2005
Адрес: Москва
|
Цитата:
Сообщение от Lucky13
Задача сформировать прайс-лист, т.е. вывести все позиции, которые находятся на складе X в количестве больше Y (частный случай >0). Простейшее решение выполнить следующий запрос: X++: Select from InventSum
join InventDim
Where InventSum.InventDimId == InventDim.InventDimId && InventSum.AvailPhysical > Y && InventDim.InventLocationId = X Такой запрос выдает верный результат, но с увеличением количества данных время выполнения запроса растет, так как выборка идет не по индексам.
У любой сложной задачи существует простое, ясное и неправильное решение А выгрузка прайс-листа - задача в общем лсучае сложная, вон, mazzy даже людей подбирает, исходя из того, как они с ней справляются 
Цитата:
Сообщение от Lucky13
К тому же это только пример, реально обычно нужно еще откуда-то достать цену товара и сгруппировать данные каким-либо образом, например по той же цене, так как клиенты чаще всего не любят когда одна и та же номенклатура повторяется в прайсе несколько раз. В итоге получается очень тяжелый запрос. Кто какие подходы для этого использует?
Во-первых, не подходите к этой задаче с точки зрения того, как вам построить один мега-запрос, который бы выдал все нужные данные с нужными группировками и фильтрами. Это и на родном SQL не всегда получается, а уж в Аксапте с ее ограничениями по количеству связанных таблиц в запросе - и подавно. Здесь по любому придется использовать подзапросы для получения дополнительных данных. Во-вторых, подумайте о том, что именно вы выгружаете: у вас ведь не отчет по складским остаткам, а выгрузка прайс-листа. Прайс-лист - это в первую очередь номенклатура, вот от нее и пляшите. Сколько у вас всего номенклатур? Если она исчисляется не миллионами, то лучше, вероятно, сделать выгрузку, перебирающую все номенклатуры (с определенными фильтрами, скажем, по бренду), а уже внутри этого перебора делающую проверку на остатки по определенному складу, на соответствие выгружаемых цен определенным критериями, etc.
Подумайте также о том, что InventSum у вас может постоянно блокироваться при обработке движений по номенклатуре, а вы, пытаясь сделать по ней мега-запрос выгрузки прайс-листа, в свою очередь, будете блокировать других пользователей. Поэтому, опять же, кучка мелких подзапросов будет в общем случае предпочтительнее одного мега-запроса, который сначала будет ждать освобождения кучи блокировок, а потом сам надолго заблокирует таблицу, и без того являющуюся зачастую узким местом в системе.
Затем, вам наверняка потребуется предоставить пользователю возможность группировать номенклатуру в выгрузке по различным критериям: либо по бренду, либо по какому-нить классификатору номенклатуры, либо еще по чему-то... Не так давно пришлось приделывать такую сортировку, плюс немного оптимизировать выгрузку прайс-листа, в котором используется довольно много условных критериев, в результате выгрузка (на псевдокоде) получилась примерно такая:Код: инициализировать канал вывода // отдельный метод
если выгрузка в csv/Excel
сделать то-то
если выгрузка в другую базу SQL
сделать что-то другое
вывести заголовок (header) // отдельный метод
сбросить значения предыдущего бренда и классификатора
построить запрос выборки номенклатуры // отдельный метод
switch по типу сортировки
если сортировка по бренду
запрос - таблица_брендов join InventTable
если сортировка по иерархическому классификатору номенклатуры
запрос - таблица_классификации join InventTable join таблица_брендов
установить фильтры по брендам // отдельный метод
установить фильтры по номенклатуре // отдельный метод
создать QueryRun с созданным запросом по номенклатуре
цикл, пока QueryRun.next() == true
если QueryRun.changed(таблица_брендов)
если текущий бренд не должен экспортироваться // отдельный метод
установить флаг пропуска бренда
если установлен флаг пропуска бренда
continue
получить необходимве данные по текущей номенклатуре
если номенклатура не должна экспортироваться // отдельный метод
continue
switch по типу сортировки
если сортировка по бренду
если текущий бренд != предыдущий бренд
вывести заголовок бренда // отдельный метод
запомнить бренд как предыдущий
если сортировка по иерархическому классификатору номенклатуры
если текущий код классификатора не равен предыдущему
вывести стек заговлоков классификатора // отдельный метод
запомнить код классификатора как предыдущий
сбросить переменные, используемые для получения цен, и флаги
цикл по ценовым группам
если ценовая группа не должна экспортироваться // отдельный метод
// и это отдельный метод
если номенклатура с "неэкспортируемой" ценой должна пропускаться
установить флаг пропуска номенклатуры
break
continue
получить цену (PriceDiscTable) по данной ценовой группе
// опять отдельный метод
если цена (т.е. PriceDiscTable) не должна экспортироваться
// copy-paste из проверки ценовых групп
если номенклатура с "неэкспортируемой" ценой должна пропускаться
установить флаг пропуска номенклатуры
break
continue
обработать данные по цене номенклатуры // отдельный метод
если выгрузка в csv/Excel
сделать то-то
если выгрузка в другую базу SQL
сделать что-то другое
если установлен признак пропуска номенклатуры
continue
выгрузить данные по текущей номенклатуре // отдельный метод
вывести заголовок (footer) // отдельный метод
деинициализировать канал вывода // отдельный метод С нужными индексами на таблицах из запроса по номенклатуре такая выгрузка по ~70000 наименований номенклатуры отрабатывает за минуту-две, в зависимости от канала вывода.
|