|
|
|
Нестандартный (видимо…) складской учет.
|
|||
|---|---|---|---|
|
#18+
Видимо передо мной встал не совсем простой вопрос. Или я глупый… Я уже писал, но не совсем точно сформулировал вопрос. В каком то виде (мне уже все равно, сделаю как угодно лишь бы работало) хранятся данные о движение на складе. Например: «товар», «дата», «сколько получили/отгрузили» Проблема в том что надо имея на входе две даты – начало и конец периода надо получить выборку вида: «товар», «остаток на начало периода», «приход за период», «расход за период» Раньше вытягивал несколько выборок на клиент и считал все руками. Работало практически моментально. Теперь необходимо переложить все обработку на сервер, что бы клиент получал НД от него. На что мозгов хватает - очень тормозит. Использую очень ресурсоемкие запросы – либо с LEFT JOIN либо с проверкой по EXIST. Сервер затыкается секунд на 30… Помогите, кто то же наверняка сталкивался с подобной ситуацией подскажите как правильно хранить данные или делать выборку. А то уже очень не охота все на клиенте обрабатывать – ибо лишаешься всяких вкусностей вроде КвантумГрида и прочих визуальных прелестей. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.05.2003, 00:55 |
|
||
|
Нестандартный (видимо…) складской учет.
|
|||
|---|---|---|---|
|
#18+
Послушай, ведь с там не только проблема с остатками. Если ты используешь усреднённый метод учёта товаров, то цена, по которой оприходуется товар, формирует и учётную цену расходуемого товара. Короче говоря, храни остатки на все предыдущие месяцы. Для расчёта нужных показателей пиши хранимые процедуры. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.05.2003, 10:09 |
|
||
|
Нестандартный (видимо…) складской учет.
|
|||
|---|---|---|---|
|
#18+
Видимо не хватает опыта, что бы даже задать вопрос нормально. :( В моем случае цены нет. Исключительно количество. То есть что, сколько, когда ушло. Все. В общем то проблем нет, кроме того что и суммарный расход/приход за период и остатки на начало периода надо выдавать в _одной_ записи. Вот тут я запинаюсь. Раньше когда все работало на локальной машине, просто обрабатывал все на клиенте. А теперь когда пытаюсь решить все средствами SQL/IB получается очень долго – на ~800 приходов/расходов порядка 600000 операций чтения! Очень мне от этого грустно. Вот я и думая, надо ли мне делать через задницу или это по сути простая задача и я просто не могу додуматься до изящного решения. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.05.2003, 16:14 |
|
||
|
Нестандартный (видимо…) складской учет.
|
|||
|---|---|---|---|
|
#18+
А я наоборот, не представляю как можно написать запрос, который на 800 записей 600000 чтений делает. Это по своему круто! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.05.2003, 16:28 |
|
||
|
Нестандартный (видимо…) складской учет.
|
|||
|---|---|---|---|
|
#18+
А может там просто индексы расставить и PLAN вручную расписать надо? Эти тысячи чтений индексированы? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.05.2003, 18:31 |
|
||
|
Нестандартный (видимо…) складской учет.
|
|||
|---|---|---|---|
|
#18+
Не поможет. Даже если индекс (кстати составной - из пяти полей...) увеличит скорость в 10 раз (имхо фантастический вариант) то это дело не спасет, тк все равно будет гораздо медленней чем было. Поэтому я и думаю, что задачу надо решать качественно, а не количественно. Но все равно спасибо – попробую в понедельник, вдруг я что капитально не понимаю. :) Дамы и господа :) отрицательные ответы типа «нет с таким не сталкивался» и «на мой взгляд задача не банальна» тоже очень приветствуются! Я бы по крайней мере хотя бы понял в какую сторону надо вести исследования. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.05.2003, 21:37 |
|
||
|
Нестандартный (видимо…) складской учет.
|
|||
|---|---|---|---|
|
#18+
А что касается почему так много – текст привести сейчас не могу, на работе он. Но в двух словах – это не совсем запрос… 1) В начале при помощи SELECT товар FROM склад GROUP BY товар создаем список всех проходивших через склад к этому времени товаров. (Так же скорости не добавляет что уникальный ключ товара – из 5 полей, меньше ни как) 2) Через ХП подсчитываем остатки на начло периода. 3) Через ХП подсчитываем суммарный приход/ расход за период. И делаем «левое» объединение 2), 3) с 1) Не знаю как в IB реализован LEFT JOIN, но судя по количеству чтений разворачивает во что-то связанное с [NOT] EXISTS ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 30.05.2003, 22:50 |
|
||
|
Нестандартный (видимо…) складской учет.
|
|||
|---|---|---|---|
|
#18+
Будет ли работать так: Код: plaintext 1. 2. 3. 4. 5. 6. ? Или это не то что нужно? А остаток на начало периода надо как-то вложенным запросом делать (?), а лучше где-нибудь хранить. Код: plaintext Ф. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.06.2003, 00:16 |
|
||
|
Нестандартный (видимо…) складской учет.
|
|||
|---|---|---|---|
|
#18+
СОРИИИИ! Фигню написал - все-таки 17 минут первого... Код: plaintext 1. 2. 3. 4. Уникальный номер операции должен быть... Только я не знаю пока, съест ли Interbase пару таких left joinов. MySQL съест :) Вот такие приходы у меня по ночам. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.06.2003, 00:23 |
|
||
|
Нестандартный (видимо…) складской учет.
|
|||
|---|---|---|---|
|
#18+
теперь запятая лишняя... ну вобщем все понятно, дальше надо пробовать самому, извините за беспокойство, пошел спать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.06.2003, 00:25 |
|
||
|
Нестандартный (видимо…) складской учет.
|
|||
|---|---|---|---|
|
#18+
Никогда не составляй ключ первичный из рабочих полей, делай его для любой таблицы служебным (не видимым пользователю) и формируй генераторами. См по тексту (когда писал мог и описаться, но идея понятна) Предположим у нас есть таблицы: 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.... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.06.2003, 14:12 |
|
||
|
Нестандартный (видимо…) складской учет.
|
|||
|---|---|---|---|
|
#18+
PS - Забыл, что естественно для вода начальных остатков необходимо написать процедуру, которая на заданную дату (аналогично триггерам T_TOVARIN) сделает соответствующую запись. Эти процедуры необходимы для правки остатков,например, после инвентаризации. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 01.06.2003, 14:15 |
|
||
|
Нестандартный (видимо…) складской учет.
|
|||
|---|---|---|---|
|
#18+
Хранимые процедуры помогут :-)) http://romkin.pochtamt.ru/script.htm Если разберешься. accountbook - записи прихода/расхода wh_remain - остатки list_remain - остатки по складу на дату list_history - то, что, скорее всего, тебе нужно ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 04.06.2003, 13:09 |
|
||
|
|

start [/forum/topic.php?fid=40&msg=32173485&tid=1580421]: |
0ms |
get settings: |
8ms |
get forum list: |
16ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
181ms |
get topic data: |
9ms |
get forum data: |
2ms |
get page messages: |
43ms |
get tp. blocked users: |
2ms |
| others: | 231ms |
| total: | 498ms |

| 0 / 0 |
