Как бы вы смоделировали дисперсию переменных данных по общей схеме? SQL - PullRequest
2 голосов
/ 19 марта 2009

В последнее время я размышлял о некоторых вещах, и мне было интересно, каким будет ПРАВИЛЬНЫЙ способ сделать что-то вроде следующего сценария (я уверен, что ребята из DB довольно часто делают что-то подобное).

Допустим, у вас есть таблица продуктов, что-то вроде этого (MySQL):

CREATE TABLE `products` (
  `id` int(11) NOT NULL auto_increment,
  `product_name` varchar(255) default NULL,
  `product_description` text,
  KEY `id` (`id`),
  KEY `product_name` (`product_name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Здесь нет ничего необычного. Теперь предположим, что в другой таблице есть иерархия категорий, и есть отдельная таблица, которая связывает отношения «многие ко многим» с таблицей продуктов, так что каждый продукт принадлежит к какой-то категории (я опущу эти потому что это не проблема здесь).

Теперь наступает интересная часть - что, ЕСЛИ каждая из категорий обязывает дополнительный набор переменных к элементам продукта. Например, продукты в категории компьютерных мониторов должны иметь поле перечисления LCD / CRT, перечисление размера экрана и т. Д. - и некоторую другую категорию, например, у мороженого есть некоторые другие переменные, такие как аромат varchar, время хранения на полках int и т. Д.

Проблема в том, что все продукты имеют общий набор переменных (идентификатор, имя, описание и тому подобное), но есть дополнительные переменные, которые не согласуются между категориями - но все продукты должны иметь общий набор, потому что в конце концов, все они принадлежат к группе продуктов, поэтому можно запросить, например, SELECT * FROM products ORDER BY company_id (тривиальный пример, возможно, не репрезентативный, но вы получите представление).

Теперь я вижу несколько возможных решений:
- создать отдельную таблицу для каждой категории продуктов и хранить там продукты с соответствующими дополнительными переменными - глупо и не подходит для запросов

- таблица продуктов остается неизменной с общими переменными, и для каждой категории создайте отдельную таблицу с дополнительными переменными, связывающими две таблицы с JOIN - нормализовано, но возникают проблемы с производительностью и ясностью запросов - как бы отфильтровать продукты из категории (1-я таблица - продукты ) и дополнительный фильтр для дополнительных переменных (17-дюймовые ЖК-мониторы, т. е.) - это потребует хитрости SQL JOIN

- таблица products остается прежней и добавляет еще один текст типа переменной, который содержит, например, данные JSON, которые содержат дополнительные переменные - компактные и аккуратные, но не могут фильтровать переменные с помощью SQL

Я знаю, что упускаю что-то совершенно очевидное и простое - я немного устала от методов нормализации :)


edit: Я искал стекоперемещение, прежде чем задал этот вопрос безуспешно. Однако после того, как я опубликовал вопрос, я нажал на один из моих тегов «нормализация» и обнаружил несколько похожих вопросов, в результате чего я нашел «реляционный дизайн специализации обобщения». Суть этой истории в том, что это, должно быть, первое в моей жизни в интернете, что теги действительно полезны при поиске. Тем не менее, я все еще хотел бы услышать от вас, ребята, и ваше мнение.
edit2 : проблема с подходом № 2 состоит в том, что я ожидаю где-то около 1000 специализаций. Существует иерархия (глубина 1-4 уровня) категорий, и конечные узлы добавляют специализированные переменные - они накапливаются в порядке ~ 1000, поэтому было бы немного непрактично добавлять специализированные таблицы для объединения.
edit3 : Из-за огромного количества изменчивости атрибутов в моем случае предложенное «значение атрибута сущности» выглядит как путь. Здесь приходит запрос кошмаров! Спасибо, ребята.

Ответы [ 3 ]

4 голосов
/ 19 марта 2009

Сколько типов продуктов вы ожидаете? У каждого из них своя логика приложения?

Вы можете создать обобщенную модель, называемую моделью «значение атрибута сущности», но у нее МНОГО подводных камней, когда вы пытаетесь разобраться с конкретными свойствами продукта. Простые поисковые запросы иногда превращаются в настоящие кошмары. Основная идея заключается в том, что у вас есть таблица, содержащая идентификатор продукта, имя свойства (или идентификатор в таблице свойств) и значение. Вы также можете добавить в таблицы для хранения шаблонов для каждого типа продукта. Таким образом, один набор таблиц скажет вам для любого данного продукта, какие свойства он может иметь (возможно, вместе с допустимыми диапазонами значений), а другой набор таблиц скажет вам для любого отдельного продукта, какие значения.

Я бы категорически не рекомендовал использовать эту модель, поскольку она выглядит по-настоящему изящной идеей, пока вам не понадобится ее реализовать.

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

2 голосов
/ 19 марта 2009

Я делал это в Oracle.

У меня были следующие таблицы:

t_class (id RAW(16), parent RAW(16)) -- holds class hierachy.
t_property (class RAW(16), property VARCHAR) -- holds class members.
t_declaration (id RAW(16), class RAW(16)) -- hold GUIDs and types of all class instances
t_instance (id RAW(16), class RAW(16), property VARCHAR2(100), textvalue VARCHAR2(200), intvalue INT, doublevalue DOUBLE, datevalue DATE) -- holds 'common' properties

t_class1 (id RAW(16), amount DOUBLE, source RAW(16), destination RAW(16)) -- holds 'fast' properties for class1.
t_class2 (id RAW(16), comment VARCHAR2(200)) -- holds 'fast' properties for class2
--- etc.

RAW(16) - это то, где Oracle содержит GUID с

Если вы хотите выбрать все свойства объекта, введите:

SELECT  i.*
FROM    (
        SELECT  id 
        FROM    t_class
        START WITH
                id = (SELECT class FROM t_declaration WHERE id = :object_id)
        CONNECT BY
                parent = PRIOR id
        ) c
JOIN    property p
ON      p.class = c.id
LEFT JOIN
        t_instance i
ON      i.id = :object_id
        AND i.class = p.class
        AND i.property = p.property

t_property содержит материалы, которые вы обычно не ищете (например, текстовые описания и т. Д.)

Быстрые свойства на самом деле являются обычными таблицами в вашей базе данных, чтобы сделать запросы эффективными. Они содержат значения только для экземпляров определенного класса или его потомков. Это позволяет избежать дополнительных объединений.

Вам не нужно использовать быстрые таблицы и ограничивать все свои данные этими четырьмя таблицами.

Для вашей задачи это будет выглядеть так (я буду использовать строки в квадратных скобках вместо GUID для краткости):

t_class

id             parent

[ClassItem]    [ClassUnknown]
[ClassMonitor] [ClassItem]
[ClassLCD]     [ClassMonitor]

t_property

class          property

[ClassItem]    price
[ClassItem]    vendor
[ClassItem]    model
[ClassMonitor] size
[ClassLCD]     matrixType

t_declaration

id             class
[1]            [ClassLCD] -- Iiyama ProLite E1700

t_instance  -- I'll put all values into one column, disregarding type (INT, VARCHAR etc)

id             class           property         value

[1]            [ClassItem]     price            $300
[1]            [ClassItem]     vendor           Iiyama
[1]            [ClassItem]     model            ProLite E1700s
[1]            [ClassMonitor]  size             17
[1]            [ClassLCD]      matrixType       TFT

Если вам нужен какой-то сложный запрос, который ищет, скажем, size AND matrixType, вы можете удалить их из property и instance и создать другую таблицу:

t_lcd (id RAW(16), size INT, matrixType VARCHAR2(200))

id             size            matrixType

[1]            17              TFT

и используйте его для объединения с другими свойствами вместо t_declaration в запросе выше.

Но эта модель жизнеспособна даже без быстрых столов.

0 голосов
/ 20 марта 2009

Существует имя для этого шаблона. Это называется "специализация обобщения".

Если вы выполните поиск по «моделированию специализации обобщения», вы получите несколько статей о том, как это сделать. Некоторые из этих статей ориентированы на реляционное моделирование и SQL, а другие - на объектное моделирование.

...