[ОТВЕТИТЬ]
Опции темы
30.01.2009 13:48  
konst
За четыре года работы на СуперМаге - объем накопившихся ошибок иногда не позволяет увидеть реальную картину...
Например - остатки товара в закупочнх ценах - при формировании отчета по аналитической БД полученные данные - достаточно сильно отличаются от данных полученных из других источников...
Поэтому родилась идея - строить эти отчеты по оперативной БД и при этом за точку отсчета брать текущие остатки....
Наш первый отчет - остатки товара в закупочных ценах.
берем текущий остаток и привязываем его по партиям к последним приходам ...
 
30.01.2009 13:52  
deucel
Одна из целей быстрое получение отчета.
У меня выполняется за 5 минут и кол-во строк результата ~500тыс.

Код:
SELECT s.LOCATION, s.article, s.goods,
       ROUND ((CASE
                  WHEN s.goods = s.quantity                                                                                 --когда на весь остаток есть приходы
                     THEN s.totalprice
                  WHEN s.goods != s.quantity AND s.totalprice != 0                                  --когда был один приход, но меньше остатка и цена не равна 0
                     THEN s.totalprice / s.quantity * s.goods                                                                                   --вычисляем цену
                  ELSE 0                                                                                                  --при всех других вариантах цена=0руб.
               END
              ),
              2
             ) totalprice
  FROM (SELECT   z.LOCATION, z.article, AVG (z.goods) goods,                                                                                   --получаем остатк
                 SUM (CASE
                         WHEN z.quantity IS NULL
                            THEN z.goods
                         WHEN z.goods2 - z.quantity >= z.goods
                            THEN null
                         WHEN z.goods2 - z.quantity < z.goods AND z.goods >= z.goods2                             --если приходов нет, будем вычислять по ЦПП(0%)
                            THEN z.quantity                                                                               --когда кол-во приходов меньше остатка
                         WHEN z.goods2 - z.quantity < z.goods AND z.goods < z.goods2
                            THEN z.quantity - (z.goods2 - z.goods)                                      --корректируем кол-во, когда приходов больше чем остаток
                      END
                     ) AS quantity,
                 SUM (CASE
                         WHEN z.quantity IS NULL
                            THEN z.goods * z.itemprice
                         WHEN z.goods2 - z.quantity >= z.goods
                            THEN null
                         WHEN z.goods2 - z.quantity < z.goods AND z.goods >= z.goods2
                            THEN z.quantity * z.itemprice
                         WHEN z.goods2 - z.quantity < z.goods AND z.goods < z.goods2
                            THEN (z.quantity - (z.goods2 - z.goods)) * z.itemprice
                      END
                     ) AS totalprice
        FROM     (SELECT g.LOCATION, g.article, s.createdat, g.goods, s.quantity,
                         NVL (s.totalprice / s.quantity, NVL ((SELECT p.price
                                                                 FROM smprices p
                                                                WHERE p.storeloc = g.LOCATION AND p.article = g.article AND p.pricetype = 6), 0)) itemprice,
                                                                                                                      --вычисляем цену, если нет то берем ЦПП(0%), 
                                                                                                                        --если нет 0 (вариантов может быть много)
                         SUM (s.quantity) OVER (PARTITION BY g.LOCATION, g.article ORDER BY s.createdat DESC) goods2
                    /*ROW_NUMBER () OVER (PARTITION BY g.LOCATION, g.article ORDER BY s.createdat DESC) seq*/          --для проверки номера партии для артикула
                  FROM   (SELECT storeloc LOCATION, article, quantity goods
                            FROM smgoods g
                           WHERE g.quantity != 0                                                          /*AND storeloc = 3*/   -- для отбора по конкретному МХ
                                                ) g,
                         (SELECT   d.locationto LOCATION, d.createdat, s.article, SUM (s.quantity) quantity, SUM (s.totalprice) totalprice
                                                                                        --если не сделать суммирование, то возникает проблема при расчете партии
                                                                                        --если в один день было несколько приходов (получаем какбы одну поставку)
                          FROM     smdocuments d, smspec s
                             WHERE d.doctype = 'WI'                                                                                 --только приходные накладные
                               AND d.createdat > SYSDATE - 60                                                                              --за последние Х дней
                               AND d.docstate = 3                                                                                    --статус "Принят полностью"
                               AND d.opcode != 9             --не учитывать статус "Инвентаризация излишков", т.е. приходки на основании Сличительных ведомостей
                               AND s.doctype = d.doctype
                               AND s.docid = d.ID
                          GROUP BY d.locationto, d.createdat, s.article) s
                   WHERE g.LOCATION = s.LOCATION(+) AND g.article = s.article(+) AND g.goods > 0
                  UNION ALL
                                                                                                                          -- отбор данных для минусовых остатков
                  SELECT g.LOCATION, g.article, NULL createdat, g.goods, NULL quantity,
                         
--       NVL ((SELECT /*+ ORDERED USE_NL(S D)*/ MAX (s.itemprice)KEEP (DENSE_RANK LAST ORDER BY d.createdat) itemprice
--               FROM smdocuments d, smspec s
--              WHERE s.doctype = d.doctype AND s.docid = d.ID AND d.doctype = 'WI' AND d.locationto = g.LOCATION AND s.article = g.article), 0) totalprice
                                                                                                                              -- находит цену последнего прихода, 
                                                                                  --но следующий вариант работает быстрее (оставлен как демонстрация возможности)
                         NVL ((SELECT p.price
                                 FROM smprices p
                                WHERE p.storeloc = g.LOCATION AND p.article = g.article AND p.pricetype = 6), 0) totalprice
                                                                                                                        --цена (вид цены) для минусовых остатков,
                                                                                                                        --у меня вид цены ЦПП(0%) без округления
                         , NULL goods2
                    FROM (SELECT storeloc LOCATION, article, quantity goods
                            FROM smgoods g
                           WHERE g.quantity != 0                                                         /*AND storeloc = 3*/    -- для отбора по конкретному МХ
                                                ) g
                   WHERE g.goods < 0) z
        GROUP BY z.LOCATION, z.article) s
 
02.02.2009 03:06  
isi
А ты аналитику пересчитай с полной очисткой, я при закрытии периода получил приличные расхождения...
 
02.02.2009 07:31  
OlegON
Цитата:
Сообщение от isi
А ты аналитику пересчитай с полной очисткой, я при закрытии периода получил приличные расхождения...
Так о чем и речь, что достаточно мутное товародвижение поменять на оперативку.
 
02.02.2009 08:21  
isi
в середине февраля С+ обещает 27 версию с переработанным товародвижением... предлагаю пока подождать
 
02.02.2009 10:51  
konst
Основная идея - сделать несколько быстрых и оперативных отчетов для менегеров:
Остатки в закупочных ценах
Остатки по поставщикам
Что-то типа товарного отчета - чтобы была возможность видеть маржу по поставщикам, по товарным группам - не тогда когда себестоимость рассчитается - а в real-time.
(p.s. себестоимость считаем 1 раз в неделю на выходных)
 
02.02.2009 11:13  
isi
быстрых отчетов вряд ли получится, особенно в закупочных ценах, придется лопатить всю базу дабы получить движение по партиям... второе товародвижение написать хочешь?
Согласен что есть возможность часть отчетов переписать по оперативной базе, но все, которые оперируют с партиями не получится (быстрых имею ввиду)
 
02.02.2009 11:25  
konst
Запрос выложенный в начале темы - отработал за 5 минут....
Я считаю это достаточно быстро...
Основная идея - не написать новый рассчет товародвижения, а получить оперативно определенный срез данных...
При этом можно пожертвовать точностью в пользу скорости...
если проанализировать товарные остатки... то можно увидеть, что
99% товаров будут привязаны к 1-3 последним поставкам, а оставшийся 1 % можно просто рассчитать по цене последнего прихода... при этом точность данных будет ДОСТАТОЧНО высока и для оперативной работы - этого хватит... а уже бухгалтерия в своей работе будет использовать данные основанные на рассчете себестоимости...
 
02.02.2009 11:33  
isi
Цитата:
Сообщение от konst
Запрос выложенный в начале темы - отработал за 5 минут....
Я считаю это достаточно быстро...
Основная идея - не написать новый рассчет товародвижения, а получить оперативно определенный срез данных...
При этом можно пожертвовать точностью в пользу скорости...
если проанализировать товарные остатки... то можно увидеть, что
99% товаров будут привязаны к 1-3 последним поставкам, а оставшийся 1 % можно просто рассчитать по цене последнего прихода... при этом точность данных будет ДОСТАТОЧНО высока и для оперативной работы - этого хватит... а уже бухгалтерия в своей работе будет использовать данные основанные на рассчете себестоимости...
на счет достаточно высокой точности я бы не стал утверждать, особенно учитывая темпы инфляции... переубеждать не буду, но я бы не рекомендовал считать таким образом себестоимость, при таком подходе маржа может процента на 2-3 "плавать", а это очень много

но то что у Супермага собственный расчет себестоимости тоже "хромает", может в этом есть смысл, хотя в данном случае ответственность несет разработчик, а вот если сам напишешь, то тебе и отвечать и доказывать...
 
04.02.2009 13:08  
akonev
если чуть задуматься, то для оперативной работы манагеров этот подход мне кажется совершенно логичным. действительно, если товар сейчас лежит в магазине, то это может быть только товар из последних приходов.

те же остатки по поставщикам - вообще нереально посчитать по другому на базе, которую 4 года "портили". особенно, если базу обрезать.

сложнее с товарами, по которым текущий расчетный остаток не совпадает с реальным (пересорты, к примеру): излишек по пересорту полезет привязываться к старым приходам и будет портить картинку. недостача по пересорту - вообще никуда не привяжется и занизит задолженность перед поставщиком

я уж не говорю о том, что манагерский и буховский (по стандартному расчету СС) учеты должны безнадежно разползтись в разные стороны.

предлагаю подумать такую мысль: озвученный вариант манагерских отчетов - не есть ли это путь к внедрению практики периодической обрезки баз без потери данных по поставщикам.
 
 


Опции темы



Часовой пояс GMT +3, время: 15:33.

Все в прочитанное - Календарь - RSS - - Карта - Вверх 👫 Яндекс.Метрика
Форум сделан на основе vBulletin®
Copyright ©2000 - 2016, Jelsoft Enterprises Ltd. Перевод: zCarot и OlegON
В случае заимствования информации гипертекстовая индексируемая ссылка на Форум обязательна.