Форум: "Базы";
Текущий архив: 2004.02.17;
Скачать: [xml.tar.bz2];
ВнизМожно ли динамически создавать/удалять View в Интербейзе? Найти похожие ветки
← →
pp (2004-01-27 12:28) [0]Уточняю: не приведет ли к каким-либо отрицательным последствиям частое создание/удаление просмотров в Интербейзе/Фаеберде?
Частое - это несколько десятков раз на день. Собираюсь делать это при создании отчета.
← →
Sandman25 (2004-01-27 12:32) [1]Чтобы отчет извлекал данные из того же View? Как альтернатива, можно передавать select statement.
Что-то типа MakeReport(const SQLText: string), а
SqlText создавать динамически с помощью if.
← →
pp (2004-01-27 12:42) [2]Что я делаю: создаю View как результат запроса к двум таблицам с группированием данных. Далее делаю запрос по View снова группируя данные.
Что такое select statement к сожалению не знаю. Сейчас лезу читать доку.
← →
Sandman25 (2004-01-27 12:45) [3]Я имел ввиду написать прямой select из таблиц, без посредника в виде view.
Select statement - это просто select выражение, просто select.
← →
pp (2004-01-27 12:49) [4]К сожалению получить данные одним запросом у меня не получилось. Могу привести текст задачи, если Вам не составит труда подсказать решение.
← →
Romkin (2004-01-27 12:51) [5]Давно надо было, валяй
← →
jack128 (2004-01-27 12:53) [6]В принципе можно, конечно, но IB не преспособлен для частого исменния метаданных. А что ХП написать никак?
← →
Sandman25 (2004-01-27 12:58) [7][4] pp (27.01.04 12:49)
Присоединяюсь к [5] :)
← →
pp (2004-01-27 13:00) [8]Не силен в SQL.
В упрощенном виде задача выглядит так:
Первая таблица (rTrans) хранит движения (приходы/расходы) товара за месяц. Вторая (rTotal) - остатки товара на складе на конец месяца. Будем решать пока упрощенно: есть движения за один месяц, и соотв. итоги только за этот месяц. Проблемы с датами я уже сам как-нибудь продумаю.
1. rTrans - таблица движений:
r1: Integer; - код товара
s: Decimal - кво товара
tp: char(1); - "+" - приход, "-" - расход
d: Date - дата движения
2. rTotal - таблица итогов:
r1: Integer;
s: Decimal
d: Date - дата итогов, всегда первое число месяца, для которого эти итоги являются начальными
Задача: получить отчет об остатках на складе в произвольный день месяца.Проблемы:
- на конец месяца товара может не быть, а на произвольный день - есть.
- обортов по товару может и не быть, но нач. и кон. остатки есть.
Сейчас собираюсь решать так:
CREATE VIEW v11 (r1,s,tpTable) AS
SELECT r1, SUM(s),"l" FROM rTotal
GROUP BY r1
UNION
SELECT r1, SUM(s*CAST(tp||"1" AS INT)),"r" FROM rTrans
GROUP BY r1
WHERE d<EndDate
//s*CAST(tp||"1" AS INT) даст сумму приходы минус расходы.
//поле tpTable для того, чтобы одинаковые строки при объединении //запросов не игнорировались
Запрос по View даст результат:
SELECT r1, SUM(s) FROM v11
GROUP BY r1
А после - удалить View.
← →
pp (2004-01-27 13:06) [9]Уточню: для простоты будем считать что rTotal хранит только начальные итоги на этот месяц (остатки на начало месяца).
← →
Sandman25 (2004-01-27 13:07) [10]Такие вещи лучше хранимыми процедурами получать. Тогда можно будет находить ближайший "cнимок" и считать либо от следующего остатка назад, либо от прошлого вперед.
А если без ХП и только назад, то примерно так
select T.s
+coalesce((select sum(s)
from rTrans
where date <
(select max(date)
from rTotal
where r=T.r)
) and date >= myDate
and r=T.r
and tp="+"
),0)
-
+coalesce((select sum(s)
from rTrans
where date <
(select max(date)
from rTotal
where r=T.r)
) and date >= myDate
and r=T.r
and tp="-"
),0)
from rTotal T
where T.date = (select max(date) from rTotal where r=T.r)
Если coalesce нет, то есть либо nvl, либо заменить на case
← →
Sandman25 (2004-01-27 13:09) [11]Cо знаками напутал. Надо заменить + на -.
И еще - если товар закончился, то в снимке он нулевой, или вообще его уже нет? Если его уже нет, то точно лучше ХП сделать :)
← →
pp (2004-01-27 13:14) [12]Я дико извиняюсь, срочно выезжаю с работы часа на 3-4. С начальством не спорят.
← →
Romkin (2004-01-27 13:17) [13]Кажется, это уже было... ХП напиши. Уже давно эта задача решалась, никаких view не нать.
http://romkin.pochtamt.ru/script.htm
ACCOUNTBOOK - как раз приход/расход, MODEL_ID - код товара, COUNTNUM - количество.
WH_REMAIN - как раз остатки, правда, на каждый день движения, а не на месяц. ДУмаю, не принципиально. Корректируются триггерами ACCOUNTBOOK_WH_...
Процедура LIST_REMAIN как раз выдает остатки на данный момент. НА указанный день - думаю, условие ввести несложно, сюда:
SELECT MAX(DATA) FROM WH_REMAIN
WHERE MODEL_ID = :MODEL_ID and DATA <= :Data
INTO :DATA;
Разбирайся, модифицируй :)
← →
Sandman25 (2004-01-27 13:27) [14]select T.s
-coalesce((select sum(s)
from rTrans
where date <
(select max(date)
from rTotal
where r=T.r
and date >= myDate)
) and date >= myDate
and r=T.r
and tp="+"
),0)
+
+coalesce((select sum(s)
from rTrans
where date <
(select max(date)
from rTotal
where r=T.r
and date >= myDate
) and date >= myDate
and r=T.r
and tp="-"
),0)
from rTotal T
where T.date = (select max(date) from rTotal where r=T.r and date >= myDate)
← →
pp (2004-01-28 11:10) [15]>Romkin
Если я понял данный пример, то в нем в ХП обходят весь справочник товаров и для каждой позиции суммируют итог с движениями за период.
Данный подход даст правильный результат, но он далек от оптимального: в справочнике может быть 10 000 позиций, а остатков может быть 100. Кроме того, если остатки будут хранится еще и в разрезе Складов/Товара/Валют (как фактически у меня) то получится уж очень много лишних движений.
>Sandman25
Если на конец месяца остаток 0, то такого товара в rTotal не будет.
Если я правильно понял Ваше решение, то такие товары выпадут из отчета.
← →
Sandman25 (2004-01-28 11:21) [16][15] pp (28.01.04 11:10)
Именно так.
Напишите ХП, которая будет считать остатки по всем товарам, которые либо были в остатках, либо были в движении.
select r from rTotal
where date = (select min(date) from rTotal where date >= myDate)
union
select r from rTrans
where date between myDate and (select min(date) from rTotal where date >= myDate)
Либо можно к моему select добавить:
union
select r, coalesce((select sum(s)
from rTrans
where date <
(select max(date)
from rTotal
where r=T.r
and date >= myDate
) and date >= myDate
and r=T.r
and tp="-"
),0) -
coalesce((select sum(s)
from rTrans
where date <
(select max(date)
from rTotal
where r=T.r
and date >= myDate
) and date >= myDate
and r=T.r
and tp="+"
),0)
from SpravochnikTovarov S
where not exists (select 1 from rTotal where r=S.r and date > myDate)
and exists (select 1 from rTrans where r=S.r and date > myDate)
← →
Sandman25 (2004-01-28 11:21) [17]Ну и еще Group by, конечно.
← →
Romkin (2004-01-28 12:11) [18]2pp Нет, в WH_REMAIN хранится именно остаток на указанную дату, нужно просто найти наибольшую дату, меньшую данной, и выбрать количество. А вот то, что весь справочник обходится, увы, таковы требования. Кстати, на 10000 наименований я тестил, пара секунд уходит. Правто, столько их у нас нет.
То, что в скрипте - не догма, а руководство к действию.
Процедурой все, это удобно. Например, если мне не потребуется показывать товар, которого нет на складе, ессно, введу еще одну таблицу, в которой будет отмечаться товар с нулевым остатком, и чуть изменю процедуру.
А разрез складов я скоро вводить буду :)
Страницы: 1 вся ветка
Форум: "Базы";
Текущий архив: 2004.02.17;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.009 c