Каков наилучший подход в SQL для хранения многоуровневых описаний? - PullRequest
1 голос
/ 28 декабря 2010

Мне нужен новый взгляд на то, как спроектировать надежную и эффективную базу данных SQL для хранения многоуровневых массивов данных.

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

Все продукты описаны одинаково. Для всех деталей требуются одинаковые поля для их описания (скажем, цена, вес, название детали), все элементы всех деталей также имеют единый дизайн (например, код элемента, производитель). Просто и понятно.
Один элемент может относиться только к одной части, а каждая часть относится только к одному продукту.

Я придумал идею трех таблиц:

Products:
--------------------------------------------
prod_id   prod_name   prod_price   prod_desc 
1            hoover          120      unused

1012 * следующий *

Parts:
----------------------------------------------------
part_id  part_name  part_price  part_weight  prod_id
      3     engine          10           20        1

и наконец

Elements:
---------------------------------------
el_id  el_code  el_manufacturer part_id
    1    BFG12               GE       3

Теперь выберите нужный продукт, выберите все из ЧАСТЕЙ, где prod_id одинаков, а затем выберите все из ELEMENTS, где совпадает part_id - после нескольких запросов вы получите все данные.

Я просто не уверен, что это правильный подход.
У меня есть еще одна идея, без таблицы ELEMENTS.
Это уменьшит количество запросов, но я немного боюсь, что это может быть хромой и плохой практикой.
Вместо таблицы ELEMENTS в таблице PARTS есть еще два поля, поэтому это выглядит так:
part_id, part_name, part_price, part_weight, prod_id, part_el_code, part_el_manufacturer
они будут иметь тип text , и для каждой части информация об элементах будет храниться в виде строк следующим образом:

part_el_code         | code_of_element1; code_of_element2; code_of_element3

part_el_manufacturer | manuf_of_element1; manuf_of_element2; manuf_of_element3

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

Причина, по которой я придумал второй вариант, заключается в том, что третья таблица - Элементы - в конечном итоге станет довольно большой. Если имеется 10 000 продуктов, 4 части для каждого продукта и в среднем 3 элемента на часть - это означает, что в таблице элементов должно быть 120 000 строк. И, честно говоря, я не знаю, приведет ли это к проблемам с производительностью.

Должен ли я просто пойти с первой идеей? Или, может быть, есть лучший подход к этой проблеме?

Ответы [ 2 ]

2 голосов
/ 28 декабря 2010

Описание отношений между вещами - это именно то, что делают реляционные базы данных.В любой книге по SQL должно быть много примеров, и я предлагаю поискать такую ​​книгу, чтобы лучше понять эти проблемы, но я дам быстрый ответ на ваш вопрос.

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

select * 
from product
join parts on parts.prod_id = product.prod_id
join elements on elements.part_id = part.parts_id
where product.prod_id = x

Это нормально и будет делать именно то, что вам нужно.


НасколькоВы, 2-я идея, это действительно плохо.Вы работаете с реляционной базой данных, она позволяет хранить наборы данных и связывать их.Хранить список в строковом значении означает игнорировать точную функциональность, для которой реляционные базы данных предназначены для успешной работы.


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

Сначала удалите prod_id из таблицы деталей, а затем удалите part_id из таблицы элементов.

Затем создайте две "соединяющие таблицы".Позволяет называть их prodparts и partselement.Они бы выглядели так:

prodparts would contain two columns prod_id and part_id (and maybe a count?)
partselement would contain two columns part_id and el_id (and maybe a count?)

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

Выбор только немного сложнее и выглядит так:

select * 
from product
join prodparts on procparts.prod_id = product.prod_id
join parts on parts.part_id = prodparts.part_id
join partselement on partelement.part_id = parts.part_id
join elements on elements.el_id = partelement.parts_id
where product.prod_id = x
0 голосов
/ 28 декабря 2010

Ваш первый подход кажется довольно солидным.Второй подход затруднит ведение данных элементов.Одна вещь, которую я заметил в первом дизайне, состоит в том, что у продукта и частей есть "цена".Они означают что-то другое или сумма цен на запчасти равна окончательной цене продукта?Если это так, я рекомендую удалить поле цены на уровне продукта и использовать функцию sum () на уровне деталей.

Кроме этого ... хорошая работа!

...