#mysql
Вопрос:
Есть две таблицы, т. е. пользователь и атрибут.
таблица пользователей-
-----------------------------------------------------------------------
| user_id | u_at1 | u_at2 | u_at3 | u_at4 | u_atN |
-----------------------------------------------------------------------
| 1 | 3 | 4 | 6 | 100 | Null |
-----------------------------------------------------------------------
| 2 | Null | 623 | Null | 85 | 1 |
-----------------------------------------------------------------------
таблица атрибутов
-----------------------
| at_id | at_text |
-----------------------
| 1 | at1 |
-----------------------
| 2 | at2 |
-----------------------
| 3 | at3 |
-----------------------
| 4 | at4 |
-----------------------
| 5 | at5 |
-----------------------
| 6 | at6 |
-----------------------
| 85 | at85 |
-----------------------
| 100 | at100 |
-----------------------
| 500 | at500 |
-----------------------
| 623 | at623 |
-----------------------
В таблице атрибутов хранятся идентификатор атрибута и текст атрибута. В таблице пользователей в столбце атрибутов пользователя (например, u_at3) хранится идентификатор атрибута. В таблице пользователей столбец u_atN является, например, целевым, т. е. количество столбцов атрибутов может быть u_at20. Вот почему я не включил сюда всю колонку.
Теперь мой вопрос: это нормально, если я сделаю ЛЕВОЕ СОЕДИНЕНИЕ 20 раз для одной и той же таблицы или есть какой-либо другой способ, которым я могу это сделать? Вот мой вопрос-
SELECT
`user`.*,
`attribute1`.`at_text`,
`attribute2`.`at_text`
`attribute3`.`at_text`
`attribute4`.`at_text`
.....................
.....................
`attribute20`.`at_text`
FROM `user`
LEFT JOIN `attribute` `attribute1` ON `user`.`u_at1` = `attribute1`.`at_id`,
LEFT JOIN `attribute` `attribute2` ON `user`.`u_at2` = `attribute2`.`at_id`,
LEFT JOIN `attribute` `attribute3` ON `user`.`u_at3` = `attribute3`.`at_id`,
LEFT JOIN `attribute` `attribute4` ON `user`.`u_at4` = `attribute4`.`at_id`,
...................................................................
...................................................................
JOIN `attribute` `attribute20` ON `user`.`u_at20` = `attribute20`.`at_id`,
WHERE `user_id` = 2;
Комментарии:
1. Нормализуйте свою схему
Ответ №1:
При использовании агрегации MySQL вы можете использовать функцию агрегации MAX() для строк, чтобы выполнить полное объединение и использовать оператор if для использования значения атрибута или null для каждого поля в зависимости от соответствия идентификатора. Затем агрегируйте по идентификатору пользователя!
Пример.
SELECT `user_id`,
MAX(IF(`attribute`.`at_id`=`user`.`u_at1`,`attribute`.`at_text`,NULL)) as `u_at1_value`,
MAX(IF(`attribute`.`at_id`=`user`.`u_at2`,`attribute`.`at_text`,NULL)) as `u_at2_value`,
MAX(IF(`attribute`.`at_id`=`user`.`u_at3`,`attribute`.`at_text`,NULL)) as `u_at3_value`,
MAX(IF(`attribute`.`at_id`=`user`.`u_at4`,`attribute`.`at_text`,NULL)) as `u_at4_value`
FROM `user`,`attribute`
GROUP BY `user_id`
С точки зрения производительности, я думаю, что быстрее использовать подзапросы для каждого поля, хотя из-за оптимизатора MySQL.
SELECT `user_id`,
(SELECT `at_text` FROM `attribute` WHERE `user`.`u_at1` = `attribute`.`at_id`) as `u_at1_value`,
(SELECT `at_text` FROM `attribute` WHERE `user`.`u_at2` = `attribute`.`at_id`) as `u_at2_value`,
(SELECT `at_text` FROM `attribute` WHERE `user`.`u_at3` = `attribute`.`at_id`) as `u_at3_value`,
(SELECT `at_text` FROM `attribute` WHERE `user`.`u_at4` = `attribute`.`at_id`) as `u_at4_value`
FROM `user`
Ответ №2:
Я думаю, что это не очень хороший подход. Вы можете получить много повторяющихся результатов, если идентификаторы атрибутов одинаковы для разных идентификаторов. Более того, 20 левых соединений в СУБД сделают вашу базу данных покрытой коркой и являются нереалистичным подходом. Чтобы решить вашу проблему, вы можете изменить дизайн базы данных.
user table:
user_id
attribute_id
И
Attribute table:
attribute_id,
text1_column
text2_column
text3_column
....
.....
text20_column
Затем вы просто выполняете одно соединение, выбираете данные из своей базы данных. Обработайте и в каком столбце вы найдете данные, используйте их в соответствии с вашими потребностями.
Я не говорю, что это лучшее решение, но, по крайней мере, это значительно уменьшит вашу сложность.
Комментарии:
1. спасибо за ваш комментарий. Повторяющегося результата можно избежать, добавив псевдоним столбца. Но моя главная забота-это производительность для 20 левых соединений.
2. вы правы насчет повторяющихся результатов. А что касается производительности, то существует огромная вероятность того, что ваше приложение застрянет, а база данных будет заблокирована в течение длительного времени, что нежелательно. Для каждого левого соединения сложность увеличивается, как этот MxN1xN2x….N20, который, я полагаю, вам вообще не нужен в вашей системе!