Показать сообщение отдельно
Старый 03.12.2007, 12:50   #9  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5803 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Цитата:
Сообщение от 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 наименований номенклатуры отрабатывает за минуту-две, в зависимости от канала вывода.