Таблица Goods (Товары)

Архангельский Андрей

Общие положения

       Как пример очень сложного дерева можно привести таблицу Goods(Товары), которая применяется от бухгалтерии и магазина до оказания услуг и страхования.
       Главное, что отличает эту категорию от других, это различные виды классификации товаров:
       — классификация товаров, которую использует продавец (или торговая фирма) у себя на складе или прилавке.
       — классификация товаров по "Товарной Номенклатуре ВнешнеЭкономической Деятельности"
       — классификация товаров по штрих-кодам EAN-13 или UPC
       — классификация товаров по каталогу фирмы-производителя
       — поиск аналогичных товаров.

       Построение дерева аналогов начинается с описания "родительского товара". Например, есть деталь для автомобиля ВАЗ с полным конструкторским номером. Эта же деталь упоминается в каталогах ВАЗа для нескольких моделей автомобиля ВАЗ и в нескольких узлах одной модели. И, наконец, эта же деталь, выпущенная другими заводами в качестве запасной части. Деталь с полным конструкторским номером примем как "родительскую", а остальные запишем как "потомков" этой детали. Тогда выбрав деталь из одного из каталогов, получаем запись о родительской детали, а потом о всех "детях" этой "родительской" детали. Таким образом получиться полный список аналогов.

       Таким образом в одной таблице получается ПЯТЬ деревьев. Запись о товаре всегда будет одна, но ее поиск может быть произведен пятью разными способами, в зависимости от конкретной ситуации. Кроме поиска не нужно забывать про возможность передвигаться по деревьям и группировать элементы в зависимости от того, в каком дереве находиться данная группа, суммировать данные из другой таблицы по уровням конкретного дерева этой таблицы.
       Само построение таблицы не вызывает особых сложностей — достаточно расширить поля образующие иерархическую структуру до пяти групп (FB_SQL\DBCreate.doc):

Create table GOODS ( 
   GOODSNO    INTEGER NOT NULL PRIMARY KEY,
   GDPARENT   INTEGER default 0,  GDCount    Integer default 0,
                                  GDOrder    Integer default 0,
   GDPrnTNK   INTEGER default 0,  GDCntTNK   Integer default 0,
                                  GDOrdTNK   Integer default 0,
   GDPRNBAR   INTEGER default 0,  GDCntBAR   Integer default 0,
                                  GDOrdBAR   Integer default 0,
   GDPRNFRM   Integer default 0,  GDCntFRM   Integer default 0,
                                  GDOrdFRM   Integer default 0,
   GDPRNAls   Integer default 0,  GDCntAls   Integer default 0,
                                  GDOrdAls   Integer default 0,
   GDTreeNo   SmallInt default 1,
   GDNames    AZTitle,    -- наименование товара в сокращенном виде для прайсов
   GOODNAMR   AZLEGEND,   -- полное наименование товара на русском языке
   GOODNAME   AZLEGEND,   -- полное наименование товара на английском языке
   GDTradMrk  AZNames,    -- торговая марка
   GDTNVED    AZNOTXT,    -- Код товара по ТН ВЭД
   GDEANCODE  AZNOTXT,    -- Код товара по EAN-13
   GDUPCCODE  AZNOTXT,    -- Код товара по UPC
   GDFIRMCOD  AZNOTXT,    -- Каталожный код товара
   GDINTCODE  AZNOTXT,    -- Внутрифирменный код товара
   GdHintTXT  AZNOVIN,    -- Текст подсказки
   GdHintX    Integer,    -- Координата X подсказки
   GdHintY    Integer,    -- Координата Y подсказки
   GDDESCRPT  AZNotes,    -- описание – текст
   GDImages1  AZBLOB);    -- описание – графика
Commit;
Insert into GOODSNew(GoodsNo,GDParent,GDPrnTNK,GdPrnBar,GdPrnFrm,GdPrnAls,
                     GdNames,GdFirmCod,GdIntCode)
 values(0,0,0,0,0,0,'Выберите тип дерева','.','.');
Commit;
Alter table Goods add foreign key(GdParent) references Goods on update cascade;
Alter table Goods add foreign key(GdPrnTNK) references Goods on update cascade;
Alter table Goods add foreign key(GdPrnBAR) references Goods on update cascade;
Alter table Goods add foreign key(GdPrnFrm) references Goods on update cascade;
Alter table Goods add foreign key(GdPrnAls) references Goods on update cascade;
Commit;

       Назначения некоторых полей:
       GDNames — сокращенное название товара для накладных. Оно должно быть достаточно короткое, чтобы укладываться в одну-две строки обычной накладной или счета (прайс-листа) и должно быть уникальным. Однако установить ограничение уникальности невозможно, так как при построении дерева возможны повторения в этом поле. Следует также учесть по это поле участвует в индексе, следовательно на его длину накладываются ограничения индекса.
       GoodNamR, GoodNamE — точное (подробное) наименование товара на русском и английском языке. Оно может быть достаточно большим, до 2000 символов.
       GdINTCode, GdTNVED, GdEANCode, GdUPCCode, GdFirmCod — уникальный код товара в различных классификациях. Текстовое поле длиной 16-18 символов. Применяется в накладных, оборотных ведомостях и в других отчетах.
       Остальные поля описательного плана.
       GoodsNo — идентификатор записи о товаре, который зависит от полей GdINTCode, GdFirmCod, GDNames.
       GdTreeNo — номер дерева, вспомогательное поле, назначение которого будет понятно позже.
       Так как деревьев много, то необходимо определить уникальность через ограничения/индексы. Не все поля могут участвовать в индексах. Так, например, EAN код, который должен быть уникальным для каждого товара, на самом деле таковым не является. Причем нарушают правило как российские так и иностранные фирмы. Часто товары одного класса, например, йогурт имеющие разные начинки маркируются одним кодом. Это касается йогурта "Fruchtegut" фирмы Mertinger (Германия), шампуни фирмы L'Oreal (Франция), глазурованных сырков фирмы СоюзКонтракт (Россия). В дереве TNVED вообще целая группа товаров имеет один код. Таким образом остается только 2 дерева, по которым можно и нужно строить уникальные индексы:

Alter table GOODS add constraint uniGdIntCode unique (GdIntCode,GdNames);
Alter table GOODS add constraint uniGdFirmCod unique (GdFirmCod,GdNames);

       Естественно, что для управления счетчиками детей триггеры нужно немного расширить, так же как это было сделано в таблице Person.

SET TERM !! ;
CREATE TRIGGER GOODS_Insert FOR GOODS
ACTIVE BEFORE INSERT POSITION 1 
AS
BEGIN
   Update GOODS SET GDCount =GDCount+1  where GoodsNo=new.GDParent;
   Update GOODS SET GDCntTNK=GDCntTNK+1 where GoodsNo=new.GDPrnTNK;
   Update GOODS SET GDCntBAR=GDCntBAR+1 where GoodsNo=new.GDPrnBAR;
   Update GOODS SET GDCntFRM=GDCntFRM+1 where GoodsNo=new.GDPrnFRM;
   Update GOODS SET GDCntAls=GDCntAls+1 where GoodsNo=new.GDPrnAls;
END !!
SET TERM ; !!
Commit;

SET TERM !! ;
CREATE TRIGGER GOODS_Update FOR GOODS
ACTIVE BEFORE UPDATE POSITION 0
AS
BEGIN
If (old.GDParent<>new.GDParent) then
    begin
      Update GOODS SET GDCount =GDCount-1  where GoodsNo=old.GDParent;
      Update GOODS SET GDCount =GDCount+1  where GoodsNo=new.GDParent;
    End
If (old.GDPrnTNK<>new.GDPrnTNK) then
    begin
      Update GOODS SET GDCntTNK=GDCntTNK-1 where GoodsNo=old.GDPrnTNK;
      Update GOODS SET GDCntTNK=GDCntTNK+1 where GoodsNo=new.GDPrnTNK;
    End
If (old.GDPrnBAR<>new.GDPrnBAR) then
    begin
      Update GOODS SET GDCntBAR=GDCntBAR-1 where GoodsNo=old.GDPrnBAR;
      Update GOODS SET GDCntBAR=GDCntBAR+1 where GoodsNo=new.GDPrnBAR;
    End
If (old.GDPrnFRM <>new.GDPrnFRM) then
    begin
      Update GOODS SET GDCntFRM=GDCntFRM-1 where GoodsNo=old.GDPrnFRM;
      Update GOODS SET GDCntFRM=GDCntFRM+1 where GoodsNo=new.GDPrnFRM;
    End
If (old.GDPrnAls <>new.GDPrnAls) then
    begin
      Update GOODS SET GDCntAls=GDCntAls-1 where GoodsNo=old.GDPrnAls;
      Update GOODS SET GDCntAls=GDCntAls+1 where GoodsNo=new.GDPrnAls;
    End
END !!
SET TERM ; !!
Commit;

SET TERM !! ;
CREATE TRIGGER GOODS_Delete FOR GOODS
ACTIVE BEFORE DELETE POSITION 0
AS BEGIN
    Update GOODS SET GDCount =GDCount-1  where GoodsNo=old.GDParent;
    Update GOODS SET GDCntTNK=GDCntTNK-1 where GoodsNo=old.GDPrnTNK;
    Update GOODS SET GDCntBAR=GDCntBAR-1 where GoodsNo=old.GDPrnBAR;
    Update GOODS SET GDCntFRM=GDCntFRM-1 where GoodsNo=old.GDPrnFRM;
    Update GOODS SET GDCntAls=GDCntAls-1 where GoodsNo=old.GDPrnAls;
END !!
SET TERM ; !!
Commit;

       Таким образом, само простроение таблицы Goods с пятью деревьями не вызывает проблем. Все хранимые процедуры, которые были описаны для таблицы Persons, таким же образом могут быть расширены для работы с таблицей Goods. Проблемы начинаются в том случае, когда необходимо отобразить эту таблицу в виде дерева.

© 01.08.2009, Архангельский А.Г.

<<Пред. Оглавление
Об Авторе
Все персоны
Главная страница
След.>>



Поддержите культуру
ЯндексЯндекс. ДеньгиХочу такую же кнопку

Google
 
Web azdesign.ru az-libr.ru


Дата последнего изменения:
Wednesday, 23-Oct-2013 09:02:58 UTC