2013-07-15 3 views
1

Я уверен, что об этом уже спрашивали/отвечали, но я не знаю, как это действие называется, и мои знания SQL ограничены.MySQL один оператор для объединения двух таблиц

Я ищу одного оператора SQL, чтобы объединить две таблицы:

Таблица USER:

ID hash 
========= 
1 abc 
2 def 
3 ghi 

и USER_FIELD стол:

ID user_id key  value 
============================= 
1 1  firstname John 
2 1  lastname Doe 
3 2  firstname Justin 
4 2  lastname Case 

Теперь я хотел бы знать, Как получить этот вид:

ID hash firstname lastname 
================================ 
1 abc John  Doe 

Итак, если я добавлю дополнительную запись в таблицу USER_FIELD с ключом «email», я получаю новый столбец в последнем результате

Возможно ли это только в MySQL или мне нужно пойти и изменить результат в PHP?

Это даже хороший дизайн DB или я должен бросить ли это идти с другой (какой?)

+0

http://stackoverflow.com/questions/806882/update-multiple-tables-in-mysql-using-left-join –

ответ

1

Пара совпадений сделала бы трюк.

SELECT u.id, u.hash, uf_f.value AS firstname, uf_l.value AS lastname 
FROM user AS u 
LEFT JOIN user_field AS uf_f ON uf_f.user_id = u.id AND uf_f.key = 'firstname' 
LEFT JOIN user_field AS uf_l ON uf_l.user_id = u.id AND uf_l.key = 'lastname' 
+0

выглядит хорошо :). Сколько еще «LEFT JOINs» можно добавить? – Xaver

0

Вы хотите использовать JOIN -statement и использовать идентификатор и user_id в качестве субъектов.

+0

, но мне не нравится, что «firstname» является именем столбца, а не значение столбца «значение» – Xaver

+0

Я вижу, если вы хотите, чтобы это «просто работает», проверьте остальные ответы. –

2

Вы можете сделать это с помощью join и group by:

select u.*, firstname, lastname 
from user u join 
    (select uf.user_id, 
      max(case when key = 'firstname' then value end) as firstname, 
      max(case when key = 'lastname' then value end) as lastname 
     from user_field uf 
     group by user_id 
    ) uf 
    on uf.user_id = u.id; 

Вы также можете сделать это с последовательностью объединений:

select u.*. firstname.value, lastname.value 
from user u join 
    user_field firstname 
    on u.id = firstname.user_id and firstname.key = 'firstname' join 
    user_field lastname 
    on u.id = lastname.user_id and lastname.key = 'lastname'; 

Ваш результат, кажется, ограничить это только одному пользователю Я бы. Возможно, вам понадобится предложение where с этим фильтром.

+0

Зачем вам нужен 'max()' в первом запросе? – DevZer0

0

Другой простой способ получения данных с помощью подзапроса.

SELECT hash, (select value from USER_FIELD where key = 'firstname' and user_id=6) as firstname, (select value from USER_FIELD where key = 'lastname' and user_id=6) as lastname FROM `USER` where ID = 6 

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

2

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

Причина, по которой вы избегаете этого, заключается в том, что вы хотите получить N пользовательское свойство, которое вы должны выполнить N-1 в MySQL, и, возможно, динамически генерировать запрос в приложении, которое является субоптимальным. Просто поместите все стандартные данные в одну таблицу, и вы можете использовать эту таблицу user_field для настраиваемых полей, которые извлекаются только по запросу.

Если вы застряли в этой структуре, чтобы иметь возможность эффективно выполнять запрос, я бы изменил таблицу user_field, чтобы не иметь идентификатор auto_increment и, скорее, сделать user_id и открыть PRIMARY KEY для таблицы. Таким образом, все поля для пользователя окажутся рядом друг с другом в табличном пространстве (при условии, что вы используете InnoDB), и поиск будет первичным поиском ключей.Еще одним шагом будет изменение ключа для tinyint и использование идентификаторов поиска вместо фактических символов (вы даже можете использовать CONSTANTS в коде, чтобы сделать его более чистым).

Смежные вопросы