Перейти к содержимому

Фотография

БД, структура таблицподскажите оптимальный вариант


  • Авторизуйтесь для ответа в теме
Сообщений в теме: 19

#1
p@R@dOx...

p@R@dOx...
  • Завсегдатай
  • 105 сообщений
Привет.
Планируется создание каталога продукции, причем каталог пятиуровневый. Причем сам продукт может быть как на третьем так и на пятом уровне.
Например:

- Камеры:
1. Бортовые:
а. Черно-белые:
*камера 1
*камера2
б. Цветные:
*камера3
2. Домашние:

- Карточки:
1. программные
*карточка1
*карточка2
2. железные.

Что-то вроде http://www.novuscctv.com/en/node/2


Как лучше создать таблицы? Какую структуру БД сочинить под это?
Первое что приходит в голову создать пять таблиц под категории и одну под сами продукты, но там такая паутина начнется с перекрестными ссылками...

Сообщение отредактировал p@R@dOx...: 06.02.2008, 16:40:05

  • 0

#2
Партизан

Партизан
  • В доску свой
  • 1 370 сообщений
Как-то была примерно такая же задача...

Создал одну таблицу, с множеством столбцов. Какие это могут быть параметры...
У каждого предмета, есть к примеру общие параметры... размер, материал, вес, цвет и т.д. Это то что можно объединить для всех товаров например. А то что неодинаково, примерно посчитайте сколько таких параметров может быть максимально, и просто оставляйте эти поля пустыми если у товара таких параметров нет.
И незачем заморачиваться на кучу таблиц. Вы просто будете выдергивать по общему признаку те или иные товары, например чтоб дернуть все камеры:
1. выбираем все товары у которых есть не пустое поле камера, или название товара соответствует камере...
2. выбираем по непустому значению в поле Lx или Matrix... ну и т.д. и т.п.
Главное, примерно посчитать сколько столбцов понадобится, и если не уверены, лучше сделать на пару больше.

И что еще... незачем создавать пять категорий... можно создать одно лишнее поле для этих категорий...

Сообщение отредактировал Partizan_: 06.02.2008, 21:09:10

  • 0

#3
p@R@dOx...

p@R@dOx...
  • Завсегдатай
  • 105 сообщений
Спасибо, Partizan_

Вот чего намудрил в итоге:

Таблица category
id (идентификатор),
name (наименование категории),
picture (сопроводительная картинка),
level (уровень категории, то есть в самом верхнем будет 1, в самом нижнем 5),
final ( =1/0 признак что больше подкатегорий не будет, и следует уже смотреть таблицу продуктов).

Как вариант можно обойтись без final, но тогда каждый раз придется заглядывать в таблицу продуктов, сверяясь нет ли там чего...


Таблица product
id (идентификатор),
name (наименование продукта),
text (сопроводительный текст)
picture (сопроводительная картинка),
cat_id (идентификатор соответствия, по которому будем определять принадлежность к категории).


Такой вариант оптимальней... Кто сталкивался, подскажите как вы реализовывали подобное...

Забыл одно поле в таблице категорий....))) Очень важное поле....)

Сообщение отредактировал p@R@dOx...: 07.02.2008, 12:12:14

  • 0

#4
Gloomy

Gloomy
  • Свой человек
  • 861 сообщений
Я бы переделал так:

Таблица category
id (идентификатор),
name (наименование категории),
picture (сопроводительная картинка),
parent (если это подкатегория - положить сюда ID папы. Если топовая категория - то 0 или NULL (вопрос религии :)

При таком раскладе глубина категорий не ограниченна, да и селекты для выборки упростятся. Кстати - абсолютно стандартная техника ,)
  • 0

#5
T. Anre

T. Anre

    Data Miner

  • В доску свой
  • 2 327 сообщений
Бегло прочитал тему, так что особо не ругайте, если что. :)

Я бы переделал так:

Таблица category
id (идентификатор),
name (наименование категории),
picture (сопроводительная картинка),
parent (если это подкатегория - положить сюда ID папы. Если топовая категория - то 0 или NULL (вопрос религии :)

При таком раскладе глубина категорий не ограниченна, да и селекты для выборки упростятся. Кстати - абсолютно стандартная техника ,)

Я бы переделал так:
categories
category_id int pkey,
name varchar,
description varchar,
pictures_path varchar,
parent _id int,
path varchar,
status enum(active, blocked)
  • 0

#6
kornel

kornel
  • В доску свой
  • 9 069 сообщений
Имхо кошернее было бы varchar на char заменить, чтоб формат строки был фиксированным.
  • 0

#7
p@R@dOx...

p@R@dOx...
  • Завсегдатай
  • 105 сообщений
Йух ты, огромный всем книксен и три поклона...)))
  • 0

#8
v04bvs

v04bvs
  • В доску свой
  • 2 062 сообщений
create table CATEGORY (
	ID integer not null primary key
  , PARENT integer not null
  , NAME varchar(64) not null
<все дополнительные свойства категории>
);

create table CAMERA (
	ID integer not null primary key
  , CATEGORY_ID integer not null
<все дополнительные свойства камеры>
  , foreign key CATEGORY_ID references CATEGORY.ID on update restrict on delete restrict
);

create table CARD (
	ID integer not null primary key
  , CATEGORY_ID integer not null
<все дополнительные свойства карточки>
  , foreign key CATEGORY_ID references CATEGORY.ID on update restrict on delete restrict
);

по полям CATEGORY.PARENT, CAMERA.CATEGORY_ID, CARD.CATEGORY_ID скорее всего стоит проставить индексы.

Как-то была примерно такая же задача...

Жуть. Вы про нормализацию что-нибудь слышали?

Имхо кошернее было бы varchar на char заменить, чтоб формат строки был фиксированным.

varchar имеет фиксированную максимальную длину (и занимает всегда одинаковое количество места), просто хранит помимо самой строки ещё её длину, в отличие от char-а. Или я вас не так понял?
  • 0

#9
Gloomy

Gloomy
  • Свой человек
  • 861 сообщений

varchar имеет фиксированную максимальную длину (и занимает всегда одинаковое количество места), просто хранит помимо самой строки ещё её длину, в отличие от char-а. Или я вас не так понял?


Вообще то в SQL про хранение декларируется только что "If the string to be stored is shorter than the declared length, values of type character will be space-padded; values of type character varying will simply store the shorter string." Все остальное - "Implementation behavior". Но - Корнела я и сам не понял :D

А вот предложенная Вами v04bvs схема - мне жутко и активно не нравится! Оригинальная схема была лучше.

Вот Вы предлагаете множество таблиц типа Камеры, Карты ... - в данной ситуации это очень плохо. Завтра мы заведём ещё сотню других товаров - придётся добавлять сотню таблиц -> приехали. И это ещё самая маленькая из проблем! :eek:
Ваша схема с одной стороны - а) избыточна, а с другой б) не связанна. Смотри сам - название таблицы и есть категория (а). Но! - знание о том какой категории какая таблица соответствует в схеме отсутствует (б).
Попробуй мысленно покидать селекты и сразу поймёшь ;)
  • 0

#10
Pooh

Pooh
  • В доску свой
  • 1 898 сообщений
ИМХО нужно минимум три таблицы -- вдруг какие-то продукты будут в нескольких категориях, т.е. соотношение между категориями и продуктами "несколько к несколько" а не "один к несколько".

product
product_id
product_description

product_categories
category_id
product_id

categories
category_id
category_description
parent_id
  • 0

#11
v04bvs

v04bvs
  • В доску свой
  • 2 062 сообщений

Вообще то в SQL про хранение декларируется только что "If the string to be stored is shorter than the declared length, values of type character will be space-padded; values of type character varying will simply store the shorter string." Все остальное - "Implementation behavior". Но - Корнела я и сам не понял :lol:

Ага, спасибо. Ну по крайней мере все СУБД, с которыми я сталкивался, так делали.

Вот Вы предлагаете множество таблиц типа Камеры, Карты ... - в данной ситуации это очень плохо.

И чем это плохо? Я могу сразу сказать, чем это хорошо. Каждый продукт обладает своими уникальными характеристиками (я дальше буду говорить про компьютерные товары, камеры от меня слишком далеко, но аналоги автор проведёт). У процессора есть частота, количество ядер, производитель, ещё что то. У памяти есть её объём, количество банков, количество планок в комплекте. Хранить всё это в одной таблице если и получится, то ОЧЕНЬ некрасиво.

Завтра мы заведём ещё сотню других товаров - придётся добавлять сотню таблиц -> приехали. И это ещё самая маленькая из проблем! :lol:

Угу, приехали. Вот здесь начинается область, в которой без постановки задачи и мнения заказчика уже ничего не решишь, а можно только предполагать. Я попробую.
Итак:
1. Каждый товар обладает уникальными характеристиками, и их надо отображать в какой-нибудь таблице на сайте (любой сайт приличного компьютерного магазина). Здесь мы либо делаем сто таблиц, либо делаем одну таблицу и к ней делаем таблицу атрибутов. Для простого показа этого хватит, для поиска, фильтрации, сортировки этого не хватит. Т.е. сама постановка предполагает сложную схему и от неё никуда не денешься.
2. Все товары суть одно и то же - название, тип, примечание. В этом случае одной таблицы хватит, я не спорю. Но я не рискнул делать это предположение.
Кстати я так и не понял, в чём проблема сотни таблиц.. Добавляем Java-классы с нужными аннотациями, DDL-ки сами генерируются. При правильной организации проекта это очень просто.

Ваша схема с одной стороны - а) избыточна, а с другой б) не связанна.

Не понял, где избыточность и где несвязанность.

Смотри сам - название таблицы и есть категория (а).

Это ещё почему? Название таблицы это тип товара а не категория. По крайней мере в исходном посте я этого не увидел.

Попробуй мысленно покидать селекты и сразу поймёшь :idea:

Не понял. Имеются в виду select-ы для показа дерева? Да, здесь придётся кидать сто селектов, если у нас сто типов товаров. При желании от этого можно избавиться. Ок, следующая попытка:
create table CATEGORY (
	ID integer not null primary key
  , PARENT integer not null
  , NAME varchar(64) not null
<все дополнительные свойства категории>
);

create table PRODUCT (
	ID integer not null primary key
  , CATEGORY_ID integer not null
  , DISPLAY_NAME varchar(100) not null
  , PRODUCT_TABLE varchar(20) not null
  , PRODUCT_TABLE_ID integer not null
  , foreign key CATEGORY_ID references CATEGORY.ID on update restrict on delete restrict
);

create table CAMERA (
	ID integer not null primary key
<все дополнительные свойства камеры>
);

create table CARD (
	ID integer not null primary key
<все дополнительные свойства карточки>
);
в этом случае правда не получится сделать foreign key-ев и придётся тщательно отслеживать в софте, чтобы база не была в inconsistent state.

В общем мой point такой: разнородные вещи пихать в одну таблицу не нужно без особых на то оснований! я работал с крупной БД, в которой это не соблюдалось. Это просто ужас. Я не хочу, чтобы такое повторялось.

В общем это полиморфная схема, что то вроде

class Category {
Collection<Product> products;
Category parent;
...
}
abstract class Product {
...
}
class Camera extends Product {
...
}
class Card extends Product {
...
}

или по крайней мере она в моей голове моментально возникла в этом виде. А база у нас реляционная. Вот и натягиваем полиморфную модель на реляционную, кто как может.
  • 0

#12
Pooh

Pooh
  • В доску свой
  • 1 898 сообщений
v04bvs, а если будет не 100 а 1000 продуктов? А если в течении работы сайта за неделю по 5-6 продуктов нужно будет убирать, и создавать по 5-6 новых продуктов, и так весь год? А если я хочу чтобы когда покупатель ищет на сайте слово "Казахстан", я хочу чтобы все продукты которые ассоциируются с КЗ, сделаны в КЗ, книги про КЗ, итд., появились в результатах поиска? Как это будете программириовать, с учетом того что постоянно придется менять продуктовые таблицы и делать решения какие "дополнительные" свойства будут у каждого нового продукта? Кроме того, у вас название категории само встроено в название физической таблицы! Как вы будете элементарно на сайте отражать список продуктов -- считывать названия физ таблиц, и показывать их пользователю?
  • 0

#13
T. Anre

T. Anre

    Data Miner

  • В доску свой
  • 2 327 сообщений
Пусть нужно сделать продуктовый каталог.

Что есть продуктовый каталог?

Продуктовый каталог - это древовидный каталог типов продуктов плюс список продуктов, которые имеют свои уникальные атрибуты.

Для организации дерева типов продуктов создаем одну талицу(Дерево типов продуктов) и применяем метод "path enumeration". Помимо, дерева типов продуктов, нужна таблица(Типы продуктов) в которой бы хранились: названия атрибутов, порядок отображения и тд. и тп.

Хранение продуктов реализуем ввиде трех таблиц(Продукты, Типы атрибутов продуктов, Атрибуты продуктов). Если продуктов намечается миллионы, то отказываемся от сложных запросов в пользу простых.

Итого, имеем пять таблиц:
- Дерево типов продуктов
- Типы продуктов
- Продукты
- Типы атрибутов продуктов
- Атрибуты продуктов

Конечно, за бортом остались вопросы о: скидках, связанных продуктах, мультиязыности и тд. и тп.
Это нормально, т.к. эта модель расширяема. В итоге продукт будет выглядеть так:

Nokia N73
- Цена: 40000 тенге
- Общие характеристики:
- - Стандарт: GSM 900/1800/1900, WCDMA
- - Размеры: 110x49x19 мм
- Экран:
- - Размер изображения: 240x320 пикс.
- - Тип экрана: цветной TFT экран, 262144 цветов

Спасибо.
  • 0

#14
T. Anre

T. Anre

    Data Miner

  • В доску свой
  • 2 327 сообщений

Ваша схема с одной стороны - а) избыточна, а с другой б) не связанна.

Избыточность заметил, думаю, что в некоторых случаях это оправданно. А вот в чем же не связанность?
  • 0

#15
kornel

kornel
  • В доску свой
  • 9 069 сообщений

Имхо кошернее было бы varchar на char заменить, чтоб формат строки был фиксированным.

varchar имеет фиксированную максимальную длину (и занимает всегда одинаковое количество места), просто хранит помимо самой строки ещё её длину, в отличие от char-а. Или я вас не так понял?

Фиксированную максимальную длину. Если длина хранимой строки меньше этого параметра, то сохраняется меньше. Из-за этого вся запись не имеет фиксированной длинны. Следовательно вычислив номе строки и умножив его на длину сервер не может перейти seek()-ом к нужной записи.

ps: Народ... Прошу прощения. Это касается mysql... Не увидел, описывалось ли выше, какой именно сервер используется.
  • 0

#16
Gloomy

Gloomy
  • Свой человек
  • 861 сообщений


Ваша схема с одной стороны - а) избыточна, а с другой б) не связанна.

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


А вот напиши мне селект который вытащит ну к примеру все "ч\б камеры" - ну чего может быть проще ?

Опппа ... Ну по таблце категорий вытащишь category.id а потом?
А потом вот такой кровавый изврат (просьба детям не показывать!):
select * from camera where category_id = XXX union
select * from card where category_id = XXX union
...
select * from item99 where category_id = XXX union
select * from finally_last_prod_categoty where category_id = XXX ;

Я предложил v04bvs'у "мысленно покидать селекты" - и он сразу смекнул где бяка :D
Как видишь он ввёл поле table_name что тоже криво, но уже решает задачу с приемлимым уровнем уродства :D Это нормально - в промышленном программировании задачи решаются красиво не очень часто ;)

Далее я углубляться не буду - ибо все это будет "мысью по древу" при таких то исходных данных :) Итак с головой хватит чуваку для построения сайтика - каталога :)
  • 0

#17
Gloomy

Gloomy
  • Свой человек
  • 861 сообщений

Фиксированную максимальную длину. Если длина хранимой строки меньше этого параметра, то сохраняется меньше. Из-за этого вся запись не имеет фиксированной длинны. Следовательно вычислив номе строки и умножив его на длину сервер не может перейти seek()-ом к нужной записи.

ps: Народ... Прошу прощения. Это касается mysql... Не увидел, описывалось ли выше, какой именно сервер используется.


Ну от чего же :D В древних версиях того же оракела char'ы выбирались тоже быстрее. Правда это пофиксили где то в районе 8.1.5 - 8i - если склероз мне не изменяет ;)

В современных серьёзных сиквелях вообще что char, что varchar что text - скорость та же :D
  • 0

#18
Партизан

Партизан
  • В доску свой
  • 1 370 сообщений

Жуть. Вы про нормализацию что-нибудь слышали?

Жуткое слово... Что значит?
  • 0

#19
maratm

maratm
  • Завсегдатай
  • 213 сообщений

Я бы переделал так:

Таблица category
id (идентификатор),
name (наименование категории),
picture (сопроводительная картинка),
parent (если это подкатегория - положить сюда ID папы. Если топовая категория - то 0 или NULL (вопрос религии :D

При таком раскладе глубина категорий не ограниченна, да и селекты для выборки упростятся. Кстати - абсолютно стандартная техника ,)


ID
ID_HI

Классика, бери и не парься
  • 0

#20
maratm

maratm
  • Завсегдатай
  • 213 сообщений
//Oracle
-------------------
select * from table1 d
connect by prior d.id = d.id_hi
start with d.id_hi is null
  • 0


Количество пользователей, читающих эту тему: 1

пользователей: 0, неизвестных прохожих: 1, скрытых пользователей: 0

Размещение рекламы на сайте     Предложения о сотрудничестве     Служба поддержки пользователей

© 2011-2022 vse.kz. При любом использовании материалов Форума ссылка на vse.kz обязательна.