Forum Webscript.Ru
Общие => Базы данных => Тема начата: Kwazar от 20 Февраля 2003, 23:22:39
-
Как реализовать связь многие-ко-многим между двумя таблицами?
Пример связи многие-ко-многим:
Есть таблица продуктов
products(product_id,product_name) и таблица заказов
,назовем ее accounts(number,product_id,customer_id)
number-номер заказа,customer_id-покупатель
Но ,дело в том что покупатель может в одном заказе выбрать
несколько продуктов.
Меня интересует как предусмотреть эту возможность
и как написать запрос по одному покупателю ,который бы выводил
все продукты выбранные покупателем в данном заказе.
Заранее спасибо.
-
Еще одну таблицу
products2orders(product_id, order_id)
Запрос примерно такой будет
SELECT p.product_name FROM products p, orders o, products2orders po WHERE po.order_id = o.order_id AND p.product_id = po.product_id AND o.order_id = $order_id
(это примерно, читай про SELECT-ы по нескольким таблицам и про JOIN)
-
Хм...
Думаю, что можно соединить таблицы. В данном случае я думаю, подойдет
"естественное \'соединение".
Это означает, что можно устанавливать отношения на основе ее структуры , а
не содержимого базы, (неестественное соединение).
SELECT number,product_name,customer_id FROM products, accounts WHERE
customer_id=\'$login\'.
Я все правильно сделал?
Просто это одно из тестовых заданий, которые мне надо было решить. Хотелось бы услышать, правильно ли я сделал?
БД: Oracle
-
SELECT p.product_name FROM products p, accounts a WHERE
a.customer_id=$login and p.number = $number
-
БД: Oracle
создай представление (оно и будет аналогом 3 таблицы в mysql)
-
ThE0ReTiC, угу, я так уже и поступил, спасибо.
А MySQL поддерживает представления?
-
Можно заказанные продукты хранить числом:
т.е. напр.:
products(product_id,product_name)
1 - ананасы
2 - бананы
3 - яблоки
Тогда
accounts(number,product_id)
1 - 1 (заказали яблоки)
2 - 5 (заказали ананасы и яблоки)
3 - 7 (заказали всё)
Но тут необходимо апдейтить таблицу accounts при вставке новых записей в таблицу products.
-
Вы не совсем поняли. Возможны такие записи в таблице
accounts:
number,product_id,customer_id
1 - 19 - 17
1- 22 - 17
Т.е. number - не автоикремент.
Кстати, задача довольна интересна, т.к. виртуальные магазины работают по тому же принципу. Хотя я бы спроектировал базу по другому - но заказчик - он и в африке заказчик, к тому же, если он продвинутый.... (Бывший преподователь по базе Oracle и MsSQL). Такой проверки моих знаний мне еще ни кто не устраивал... :D
-
Kwazar
неа... :(
-
а заказчику разве не результат важен?
-
win_pup, да важен.
Только я по своему обыкновения стараюсь писать так, что бы скрипты шли на большинстве баз.
Например, Oracle - здорово, но если есть возможность без потери качества и скорости сделать так, что бы то же и в MySQL шло, то я делаю так, что бы шло и там и там. И только тогда, когда Oracle Дает в выполнении задачи явные преимущества - только тогда я ее и юзаю.
-
я имел ввиду не выбор СУБД, а то, каким образом будет реализована структура базы...
если создать таблицу-связь product_order(product_id, order_id) разве эта БД не будет работать и там и здесь?
-
Будет. Вопрос в оптимизации, интергации с другими рабочими частями.
Зачем все скручивать на проволочках? Да на них работать будет, вопрос в качестве
-
Kwazar
Будет. Вопрос в оптимизации, интергации с другими рабочими частями.
Зачем все скручивать на проволочках? Да на них работать будет, вопрос в качестве
А можно как-нибудь менее абстрактно объяснить, в чем потеря качества ? (я не придираюсь, просто самому интересно).
-
А можно как-нибудь менее абстрактно объяснить, в чем потеря качества ? (я не придираюсь, просто самому интересно).
Мне тоже интересно.:)
И, кстати, можно привести вопрос в авторской постановке?
-
Вопрос приведен именно в авторской постановке.
А оптимизация. Дело в том, что когда я с заказчиком беседовал, он мне сказал, что бы я придерживался того для БД, что он уже спроектировал. Но если учесть еще несколько сервисов, предусмотренным заказом, то для их интерации придется вводить минимум 2 лишние таблицы, со многими повторяющимяся данными. Смысла нету. Если спроектироваль все несколько иначе, то можно уменьшить количество таблиц, упростить sql запросы. Так как информации будет меньше в базах - отработка будет быстрее. Она будет в любом случае быстрая, однако я просто стараюсь сделать все проще и удобнее.
Я не говрю, что тот закачик туп или глуп - свое дело он знает. дело в том, что оно надо так извращаться?
-
я бы спроектировал базу след.образом:
таблица Покупатель:
customer
-------------------------
id_customer (key)
name
таблица Товар:
product
-------------------------
id_product (key)
name
таблица Заказ:
order
-------------------------
id_order (key)
id_customer
ну и конечно же таблица, осуществляющая связь многих-ко-многм (в заказе несколько продуктов, вид товара может быть учтён в разных заказах):
order_product
-------------------------
order_id (Key)
product_id (Key)
Нет никаких ни аномалий ни избыточности, мне кажется...
-
Кстати. Между делом... На тестовом задании, которое я здесь выложил - нельзя было создавать лишние таблицы.
Можно было оперированть только теми, что имеются на данный момент.
-
Кстати. Между делом... На тестовом задании, которое я здесь выложил - нельзя было создавать лишние таблицы.
Можно было оперированть только теми, что имеются на данный момент.
Вопрос подразумевал LEFT JOIN.
-
А чем плох такой подход:
SELECT number,product_name,customer_id FROM products, accounts USING
(product_name) WHERE
customer_id=\'$login\'.
ХОТЬ СУБД и используют внутренний оптимизатор, однако я предпочитаю делать
более точные и понятные для чтения запросы. К тому же, если в таблицах будут
другие стобцы с одинаковыми именами, то без него сложно будет обойтись.
Форма USING принимает список имен столбцов, разделенных запятвыми, где
каждое имя соответствует одному столбцу в каждой из соединяемых таблиц,
выполняет эквисоединение по всем парам столбцов с одинаковыми именами и
объединяет результаты с помощбю оператора AND. Это практически анологично
NATURAL JOIN, за исключением того, что USING использует только указанные
столбцы.
Можно также добавить INNER JOIN. При внутреннем соединении несовподающие
строки обеех таблиц исключаются.
(синтаксис привеен стандартный, а не конкретный для определенной СУДБ)
???
-
если уж так, то мне кажется, что лучше в таблице account хранить не product_name, а product_id и объединять эти таблицы по id-шнику (using product_id)... а может я и ошибаюсь...
кстати, а какое(ие) поле(я) в таблице account у тебя являе(ю)тся ключевым(и)?
-
win_pup, точно :D
Основная таблица пользователя должна содержать только родительские ключи и персональную информацию по посетителю.
Далее таблица с id заказа товара будет содержать сам заказ.
Т.е. id заказа - id товара
Далее id понадобится для проверки по таблице - наличие на складе и т.д и т.п. заморочек много. Информации тоже. Но дублируются только ключи - связь между таблицами. Остальная инфа остается уникальной. Так проще.
-
конечно :-)