Цитата: Andrew_Konev ➤ те же остатки по поставщикам - вообще нереально посчитать по другому на базе, которую 4 года "портили". особенно, если базу обрезать.
сложнее с товарами, по которым текущий расчетный остаток не совпадает с реальным (пересорты, к примеру): излишек по пересорту полезет привязываться к старым приходам и будет портить картинку. недостача по пересорту - вообще никуда не привяжется и занизит задолженность перед поставщиком
Все верно, но нужно искать компромисс.
Если предположить, что пересорт возможен только на взаимозаменяемых товарах, то сумма по группе должна быть относительно точной.
Раз была затронута тема с поставщиками, то еще один запросик попытки вычислить остатки по магазинам в закупочных ценах по поставщикам и поставкам (относительно точно и быстро). За основу был взят запрос в начале темы. Специально не группировал, чтоб было видно привязку к партиям по датам.
Код:
SELECT z.LOCATION, z.article, z.createdat, NVL (z.clientindex, -1) clientindex, z.goods,
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
THEN z.quantity
WHEN z.goods2 - z.quantity < z.goods AND z.goods < z.goods2
THEN z.quantity - (z.goods2 - z.goods)
END quantity,
(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
) totalprice
FROM (SELECT g.LOCATION, g.article, s.clientindex, s.createdat, g.goods,
CASE
WHEN COUNT (s.quantity) OVER (PARTITION BY g.LOCATION, g.article) = 1
THEN g.goods
ELSE s.quantity
END 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,
CASE
WHEN COUNT (s.quantity) OVER (PARTITION BY g.LOCATION, g.article) = 1
THEN g.goods
ELSE SUM (s.quantity) OVER (PARTITION BY g.LOCATION, g.article ORDER BY s.createdat DESC)
END goods2
FROM (SELECT storeloc LOCATION, article, quantity goods
FROM smgoods g
WHERE g.quantity > 0 AND EXISTS (SELECT /*+ INDEX (C)*/
1
FROM smcard c
WHERE c.datatype = 0 AND c.article = g.article)) g,
(SELECT /*+ INDEX(D)*/
d.locationto LOCATION, d.clientindex, 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 - 90 AND d.docstate = 3 AND d.opcode != 9 AND s.doctype = d.doctype AND s.docid = d.ID
GROUP BY d.locationto, d.clientindex, d.createdat, s.article) s
WHERE g.LOCATION = s.LOCATION(+) AND g.article = s.article(+)
UNION ALL
SELECT g.LOCATION, g.article, NULL clientindex, NULL createdat, g.goods, NULL quantity,
NVL ((SELECT p.price
FROM smprices p
WHERE p.storeloc = g.LOCATION AND p.article = g.article AND p.pricetype = 6), 0) totalprice, NULL goods2
FROM (SELECT storeloc LOCATION, article, quantity goods
FROM smgoods g
WHERE g.quantity < 0 AND EXISTS (SELECT /*+ INDEX (C)*/
1
FROM smcard c
WHERE c.datatype = 0 AND c.article = g.article)) g) z
WHERE z.quantity IS NULL OR z.goods2 - z.quantity < z.goods
Чем меньше магазинов - тем быстрее отработает (сейчас по всем)
Чем больше период (сейчас 90 дней) - тем больше точность данных привязки к партиям.
Отрицательные остатки изначально к поставщикам не привязываем и используем pricetype = 6, это же относится и к положительным если не обнаружено ни одной поставки (если и это невозможно то цена 0). Если были поставки которых не достаточно для перекрытия остатка, то не перекрытый приходами остаток будет привязан к цене и соотв. поставщику самой ранней по дате.