#mysql #sql
#mysql #sql
Вопрос:
Я действительно не знаю, как это называется, поэтому я не мог найти ответа.
Например, у меня есть следующие таблицы:
Table products Table users
---------- ---------- ---------- ---------- ----------
| id | name | price | | username | products |
---------- ---------- ---------- ---------- ----------
| 1 | Bread | 1.5 | | James | 1, 2 |
---------- ---------- ---------- ---------- ----------
| 2 | Cookies | 2.0 | | David | 2, 3 |
---------- ---------- ---------- ---------- ----------
| 3 | Milk | 1.2 | | Paul | 3, 1 |
---------- ---------- ---------- ---------- ----------
products.id
является внешним ключом для users.products
.
Я хотел бы получить название и цену всех продуктов Дэвида, используя запрос MySQL. Это должно вернуть следующее:
---------- ----------
| name | price |
---------- ----------
| Cookies | 2.0 |
---------- ----------
| Milk | 1.2 |
---------- ----------
JOIN
Я думаю, эту функцию было бы лучше всего использовать, но у Дэвида может быть только 1 или 100 продуктов. Создание 100 столбцов для всех продуктов звучит не очень эффективно.
Как я могу это осознать?
В настоящее время я просто извлекаю все и фильтрую его с помощью PHP, на данный момент это не проблема, но по мере роста таблиц, я думаю, это будет очень неэффективно.
Комментарии:
1. На самом деле это очень плохая модель… то, как вы храните идентификатор продуктов в таблице users, неверно
2. Дизайн
'Users'
стола неправильный. Вместо того, чтобы работать над этим плохим дизайном, пожалуйста, измените дизайн3. Я полагаю, вы имеете в виду, что
users.products
столбец неверен. Я знаю, что это так, но я понятия не имею, как это сделать по-другому (в настоящее время я использую JSON для PHP). Проблема в том, что продукты, которые может иметь Дэвид, различаются.4. У вас может быть несколько строк для каждого пользователя, т.Е. По одной строке для каждого продукта в
Users
таблице. Вы можете поддерживать другое логическое поле, чтобы определить, какие из них в настоящее время «активны» или «применимы».Joins'
в этом случае было бы намного проще. Кроме того, обновление записей также было бы проще. В случае, если в будущем вы захотите извлекать и анализировать данные из исторических записей, это тоже возможно!!!5. Метод, который вы описываете, является довольно стандартным способом обработки отношений «многие ко многим». У вас есть промежуточная таблица, которая содержит первичные ключи каждой таблицы, к которой вы хотите присоединиться, и вы можете получить свои результаты, объединив все три таблицы вместе.
Ответ №1:
Это можно решить, изменив вашу модель данных.
users
---------- ----------
| id | username |
---------- ----------
| 1 | Fred |
---------- ----------
| 2 | John |
---------- ----------
products
---------- ---------- ----------
| id | name | price |
---------- ---------- ----------
| 1 | Bread | 1.5 |
---------- ---------- ----------
| 2 | Cookies | 2.0 |
---------- ---------- ----------
| 3 | Milk | 1.2 |
---------- ---------- ----------
И здесь происходит волшебство: вы можете соединить две таблицы, используя третью таблицу:
user_procuct_connections
---------- ---------- ------------
| id | user_id | product_id |
---------- ---------- ------------
| 1 | 1 | 2 | -> Fred has Cookies
---------- ---------- ------------
| 2 | 1 | 3 | -> Fred also has Milk
---------- ---------- ------------
| 3 | 2 | 1 | -> John has Bread
---------- ---------- ------------
Если вы хотите, чтобы пользователь мог владеть только одним продуктом, тогда вы можете удалить столбец id user_id
и product_id
создать первичный ключ вместе.
Затем, когда вы хотите получить, например, все продукты Freds, тогда просто
SELECT
*
FROM
products
WHERE
id IN (
SELECT
product_id
FROM
user_procuct_connections
WHERE
user_id = 1
)
Ответ №2:
Вы могли бы попробовать это:
SELECT * FROM products pt
where FIND_IN_SET(pt.id,(select us.prices from users us
WHERE us.username = "David"));
Рабочая скрипка: http://sqlfiddle.com /#!2/4f78d/2
Комментарии:
1. Спасибо, это было на самом деле то, что я искал! Тем не менее, я буду использовать решение Сатвика Надкарни, потому что таким образом проще добавлять и удалять продукты.
Ответ №3:
Дизайн таблицы «Пользователи» неправильный. Вместо того чтобы обходить этот плохой дизайн, пожалуйста, измените его.
Настолько эффективно, что ваш дизайн мог бы быть таким:
Столовые Продукты :
ID Name Price
1 Bread 1.5
2 Cookies 2.0
3 Milk 1.2
Пользователи таблицы :
Username Products
James 1
James 2
David 2
David 3
Paul 3
Paul 1
Видите ли, у вас может быть несколько строк для каждого пользователя, т.Е. По одной строке для каждого продукта в таблице Users. Вы можете поддерживать другое логическое поле, чтобы определить, какие из них в настоящее время «активны» или «применимы». В этом случае Joins было бы намного проще. Кроме того, обновление записей также было бы проще. В случае, если в будущем вы захотите извлекать и анализировать данные из исторических записей, это тоже возможно!!!
Еще одна особенность текущего дизайна заключается в том, что вам снова и снова придется обходить печально известные «значения, разделенные запятыми». Допустим, у вас есть запись как таковая:
Username Products
James 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
Если вам нужно отсортировать эти данные по строкам, вам придется много раз обходить значения, разделенные запятыми. Представьте, что вы делаете это для ‘n’ количества записей!!
Надеюсь, это поможет!!!
Ответ №4:
Если вы присоединитесь к таблицам, как:
SELECT name, price FROM products AS p INNER JOIN user_products AS up ON up.id = p.product_id AND up.user_id = <davids id>
Вы получите массив, в котором первый столбец будет именем, а второй — ценой. Затем вы можете делать с ним все, что хотите, в PHP и изменять массив. Вам больше не нужно фильтровать.