powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Нестандартный (видимо…) складской учет.
13 сообщений из 13, страница 1 из 1
Нестандартный (видимо…) складской учет.
    #32172390
Antony Borovin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Видимо передо мной встал не совсем простой вопрос. Или я глупый…
Я уже писал, но не совсем точно сформулировал вопрос. В каком то виде (мне уже все равно, сделаю как угодно лишь бы работало) хранятся данные о движение на складе.
Например: «товар», «дата», «сколько получили/отгрузили»
Проблема в том что надо имея на входе две даты – начало и конец периода надо получить выборку вида:
«товар», «остаток на начало периода», «приход за период», «расход за период»

Раньше вытягивал несколько выборок на клиент и считал все руками. Работало практически моментально. Теперь необходимо переложить все обработку на сервер, что бы клиент получал НД от него.
На что мозгов хватает - очень тормозит. Использую очень ресурсоемкие запросы – либо с LEFT JOIN либо с проверкой по EXIST. Сервер затыкается секунд на 30…
Помогите, кто то же наверняка сталкивался с подобной ситуацией подскажите как правильно хранить данные или делать выборку. А то уже очень не охота все на клиенте обрабатывать – ибо лишаешься всяких вкусностей вроде КвантумГрида и прочих визуальных прелестей.
...
Рейтинг: 0 / 0
Нестандартный (видимо…) складской учет.
    #32172523
Gold
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Послушай, ведь с там не только проблема с остатками. Если ты используешь усреднённый метод учёта товаров, то цена, по которой оприходуется товар, формирует и учётную цену расходуемого товара.
Короче говоря, храни остатки на все предыдущие месяцы. Для расчёта нужных показателей пиши хранимые процедуры.
...
Рейтинг: 0 / 0
Нестандартный (видимо…) складской учет.
    #32173042
Antony Borovin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Видимо не хватает опыта, что бы даже задать вопрос нормально. :(
В моем случае цены нет. Исключительно количество. То есть что, сколько, когда ушло.
Все. В общем то проблем нет, кроме того что и суммарный расход/приход за период и остатки на начало периода надо выдавать в _одной_ записи. Вот тут я запинаюсь. Раньше когда все работало на локальной машине, просто обрабатывал все на клиенте. А теперь когда пытаюсь решить все средствами SQL/IB получается очень долго – на ~800 приходов/расходов порядка 600000 операций чтения! Очень мне от этого грустно.
Вот я и думая, надо ли мне делать через задницу или это по сути простая задача и я просто не могу додуматься до изящного решения.
...
Рейтинг: 0 / 0
Нестандартный (видимо…) складской учет.
    #32173059
Gold
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А я наоборот, не представляю как можно написать запрос, который на 800 записей 600000 чтений делает. Это по своему круто!
...
Рейтинг: 0 / 0
Нестандартный (видимо…) складской учет.
    #32173188
noir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А может там просто индексы расставить и PLAN вручную расписать надо? Эти тысячи чтений индексированы?
...
Рейтинг: 0 / 0
Нестандартный (видимо…) складской учет.
    #32173263
Antony Borovin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Не поможет. Даже если индекс (кстати составной - из пяти полей...) увеличит скорость в 10 раз (имхо фантастический вариант) то это дело не спасет, тк все равно будет гораздо медленней чем было. Поэтому я и думаю, что задачу надо решать качественно, а не количественно. Но все равно спасибо – попробую в понедельник, вдруг я что капитально не понимаю. :)

Дамы и господа :) отрицательные ответы типа «нет с таким не сталкивался» и «на мой взгляд задача не банальна» тоже очень приветствуются! Я бы по крайней мере хотя бы понял в какую сторону надо вести исследования.
...
Рейтинг: 0 / 0
Нестандартный (видимо…) складской учет.
    #32173270
Antony Borovin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А что касается почему так много – текст привести сейчас не могу, на работе он.
Но в двух словах – это не совсем запрос…
1) В начале при помощи
SELECT товар FROM склад
GROUP BY товар
создаем список всех проходивших через склад к этому времени товаров.
(Так же скорости не добавляет что уникальный ключ товара – из 5 полей, меньше ни как)
2) Через ХП подсчитываем остатки на начло периода.
3) Через ХП подсчитываем суммарный приход/ расход за период.

И делаем «левое» объединение 2), 3) с 1)

Не знаю как в IB реализован LEFT JOIN, но судя по количеству чтений разворачивает во что-то связанное с [NOT] EXISTS
...
Рейтинг: 0 / 0
Нестандартный (видимо…) складской учет.
    #32173485
Фотография fedd
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Будет ли работать так:

Код: plaintext
1.
2.
3.
4.
5.
6.
select склад.товар, sum(приходы.оборот) as приход, sum(расходы.оборот) as расход
from склад,
склад as приходы, 
склад as расходы
where склад.товар=приходы.товар and приходы.оборот >  0 
and склад.товар=расходы.товар and расходы.оборот <  0 
group by товар


? Или это не то что нужно? А остаток на начало периода надо как-то вложенным запросом делать (?), а лучше где-нибудь хранить.

Код: plaintext
select sum(оборот) from склад where дата < дата начала периода


Ф.
...
Рейтинг: 0 / 0
Нестандартный (видимо…) складской учет.
    #32173489
Фотография fedd
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
СОРИИИИ! Фигню написал - все-таки 17 минут первого...

Код: plaintext
1.
2.
3.
4.
select склад.товар, sum(приходы.оборот) as приход, sum(расходы.оборот) as расход
from склад,
left join склад as приходы on склад.уникномер=приходы.уникномер and приходы.оборот >  0 
left join склад as расходы on склад.уникномер=приходы.уникномер and приходы.оборот <  0 
group by товар


Уникальный номер операции должен быть...

Только я не знаю пока, съест ли Interbase пару таких left joinов. MySQL съест :)

Вот такие приходы у меня по ночам.
...
Рейтинг: 0 / 0
Нестандартный (видимо…) складской учет.
    #32173490
Фотография fedd
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
теперь запятая лишняя...
ну вобщем все понятно, дальше надо пробовать самому, извините за беспокойство, пошел спать.
...
Рейтинг: 0 / 0
Нестандартный (видимо…) складской учет.
    #32173550
Фотография Bol
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Никогда не составляй ключ первичный из рабочих полей, делай его для любой таблицы служебным (не видимым пользователю) и формируй генераторами.
См по тексту (когда писал мог и описаться, но идея понятна)
Предположим у нас есть таблицы:

1) T_TOVAR состав (PK-> N_TOVAR, TOVAR, и т.д....)

2) Пусть есть таблица, в которой на каждую дату накапливается количество отпущенного товара
T_SOSTOUT состав (PK->N_SOSTOUT, FK->N_TOVAR, DATE_OUT, KOLVO_OUT)

3) T_TOVAROUT состав (PK-> N_TOVAROUT, FK->N_TOVAR, KOLVO, DATE_OUT...)
Для этой таблицы делаются соответствующие триггеры

CREATE TRIGGER T_SOST_T_TOVAROUT_INS FOR T_TOVAROUT
AFTER INSERT POSITION 0
AS
DECLARE VARIABLE CNT INTEGER;
DECLARE VARIABLE OLD_KOLVO DOUBLE PRECITION;
BEGIN
выбрать число записей в таблице SOSTOUT
по данному товару за дату расхода
SELECT COUNT(N_SOSTOUT)
FROM SOSTOUT
WHERE (SOSTOUT.DATEOUT = NEW.DATE_OUT) AND
(SOSTOUT.N_TOVAR = NEW.N_TOVAR)
INTO :CNT;
если число записей за дату по этому товару = 0,
добавить запись в таблицу STATOUT по данному товару и дате
IF (:CNT = 0) THEN
INSERT INTO STATOUT (DATE_OUT, N_TOVAR, KOLVO) VALUES
NEW.DATE_OUT, NEW.N_TOVAR, NEW.KOLVO);
ELSE
иначе добавить новое количество товара
в уже существующей записи для этого товара
и этой даты в STATOUT
BEGIN
SELECT KOLVO FROM STATOUT
WHERE (STATOUT.DATE_OUT = NEW.DATE_OUT) AND
(STATOUT.N_TOVAR = NEW.N_TOVAR) INTO :OLD_KOLVO_VAL;
UPDATE STATOUT
SET KOLVO = :OLD_KOLVO_VAL + NEW.KOLVO
WHERE (STATOUT.DATE_OUT = NEW.DATE_OUT) AND
(STATOUT.N_TOVAR = NEW.N_TOVAR);
END
END

CREATE TRIGGER T_SOST_T_TOVAROUT_UPD FOR T_TOVAROUT AFTER
UPDATE POSITION 0 AS
DECLARE VARIABLE CNT INTEGER;
DECLARE VARIABLE OST_KOLVO DOUBLE PRECITION;
DECLARE VARIABLE OLD_KOLVO_VAL DOUBLE PRECITION;
BEGIN
в таблице статистики STATOUT
найти общее количество расхода
старого товара по старой дате
из таблицы T_TOVAROUT
SELECT KOLVO_OUT FROM STATOUT
WHERE (STATOUT.DATE_OUT = OLD.DAT_RASH)
AND (STATOUT.N_TOVAR = OLD.N_TOVAR)
INTO :OLD_KOLVO_VAL ;
в таблице статистики STATOUT
уменьшить общее число прихода старого товара
на старое значение количества расхода
из таблицы T_TOVAROUT
UPDATE STATOUT
SET KOLVO_OUT = :OLD_KOLVO_VAL - OLD.KOLVO
WHERE (STATOUT.DATE_OUT = OLD.DATE_OUT) AND
(STATOUT.N_TOVAR = OLD.N_TOVAR);
OST_KOLVO = OLD_KOLVO_VAL - OLD.KOLVO;
если оставшееся количество расхода за эту дату по этому товару равно 0, удалить запись из таблицы STATOUT
IF (:OST_KOLVO = 0) THEN DELETE FROM STATOUT
WHERE (STATOUT.DATE_OUT = OLD.DATE_OUT) AND
(STATOUT.N_TOVAR = OLD.N_TOVAR);
выбрать число записей в таблице STATOUT по новому товару за новую дату расхода
SELECT COUNT(N_STATOUT) FROM STATOUT
WHERE (STATOUT.DATE_OUT = NEW.DATE_OUT) AND
(STATOUT.N_TOVAR = NEW.N_TOVAR)
INTO :CNT;
если число записей = 0, добавить запись в таблицу STATOUT по новому товару и новой дате
IF (:CNT = 0) THEN
INSERT INTO STATOUT (DATE_OUT, N_TOVAR, KOLVO_OUT)
VALUES (NEW.DATE_OUT, NEW.N_TOVAR, NEW.KOLVO);
ELSE
иначе добавить новое количество товара в уже существующей записи для данного товара и новой даты в STATOUT
BEGIN
SELECT KOLVO_OUT FROM STATOUT
WHERE (STATOUT.DATE_OUT = NEW.DATE_OUT) AND
(STATOUT.N_TOVAR = NEW.N_TOVAR) INTO :OLD_KOLVO_VAL;
UPDATE STATOUT
SET KOLVO_OUT = :OLD_KOLVO_VAL + NEW.KOLVO
WHERE (STATOUT.DATE_OUT = NEW.DATE_OUT) AND
(STATOUT.N_TOVAR = NEW.N_TOVAR);
END
END


CREATE TRIGGER T_SOST_T_TOVAROUT_DEL FOR T_TOVAROUT
AFTER DELETE POSITION 0 AS
DECLARE VARIABLE OST_KOLVO DOUBLE PRECITION;
DECLARE VARIABLE OLD_KOLVO_VAL DOUBLE PRECITION;
BEGIN
в таблице статистики STATOUT
найти общее количество расхода
товара за дату
из таблицы T_TOVAROUT
SELECT KOLVO_OUT FROM STATOUT
WHERE (STATOUT.DATE_OUT = OLD.DATE_OUT) AND
(STATOUT.N_TOVAR = OLD.N_TOVAR)
INTO :OLD_KOLVO_VAL;
в таблице статистики STATOUT уменьшить общее число прихода товара на значение количества расхода товара из таблицы T_TOVAROUT
UPDATE STATOUT
SET KOLVO_OUT = :OLD_KOLVO_VAL - OLD.KOLVO
WHERE (STATOUT.DATE_OUT = OLD.DATE_OUT) AND
(STATOUT.N_TOVAR = OLD.N_TOVAR);
OST_KOLVO = OLD_KOLVO_VAL - OLD.KOLVO;
если оставшееся количество расхода по товару за
эту дату равно 0, удалить
запись из таблицы STATOUT
IF (:OST_KOLVO = 0) THEN
DELETE FROM STATOUT
WHERE (STATEOUT.DATE_OUT = OLD.DATE_OUT) and
(STATOUT.N_TOVAR = OLD.N_TOVAR)
END



Аналогично м. сделать и для поступления товара, добавляя строки с префиксом, например, ("-") в ту же таблицу T_SOSTOUT или сделав новую
T_SOSTIN. Думаю проще воспользоваться уже имеющейся таблицей.
В результате в одной таблице будет храниться вся информация по поступлению и отпуску товара и запрос из неё будет простеёшим, но конечно же надо заполнить самое первое поле для ввода остатков специальной процедурой, которая имитирует работу триггера для
TRIGGER T_SOST_T_TOVARIN_INS FOR T_TOVARIN AFTER INSERT

4) T_TOVARIN состав (PK-> N_TOVARIN, FK->N_TOVAR, KOLVO, ...)

CREATE TRIGGER T_SOST_T_TOVARIN_DEL FOR T_TOVARIN AFTER DELETE POSITION 0 AS...............

CREATE TRIGGER T_SOST_T_TOVARIN_INS FOR T_TOVARIN AFTER INSERT POSITION 0 AS..............

CREATE TRIGGER T_SOST_T_TOVARIN_UPD FOR T_TOVARIN AFTER UPDATE POSITION 0 AS..............

......ENJOY....
...
Рейтинг: 0 / 0
Нестандартный (видимо…) складской учет.
    #32173553
Фотография Bol
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PS - Забыл, что естественно для вода начальных остатков необходимо написать процедуру, которая на заданную дату (аналогично триггерам T_TOVARIN) сделает соответствующую запись. Эти процедуры необходимы для правки остатков,например, после инвентаризации.
...
Рейтинг: 0 / 0
Нестандартный (видимо…) складской учет.
    #32176159
Roman Ignatiev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хранимые процедуры помогут :-))
http://romkin.pochtamt.ru/script.htm
Если разберешься.
accountbook - записи прихода/расхода
wh_remain - остатки
list_remain - остатки по складу на дату
list_history - то, что, скорее всего, тебе нужно
...
Рейтинг: 0 / 0
13 сообщений из 13, страница 1 из 1
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Нестандартный (видимо…) складской учет.
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]