MySQL один оператор для объединения двух таблиц

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

Я ищу один оператор 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?

Является ли это даже хорошим дизайном БД, или я должен отказаться от этого варианта с другим (какой?)

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

 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' 

Вы можете сделать это с помощью 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 с этим фильтром.

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

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

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

Вы хотите использовать JOIN -statement и использовать ID и user_id в качестве объектов.

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

 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 

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