我确信这已被提出/已经回答,但我不知道这种行为是如何被调用的,而且我的SQL知识是有限的。
我正在搜索一个SQL语句来合并两个表:
表用户:
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”的addtional条目,我会在最后一个结果中得到一个新列
这甚至可以在MySQL中使用,还是我必须在PHP中改变结果?
这是一个很好的数据库设计还是我应该放弃一个不同的(哪一个?)
答案 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';
您的结果似乎将此限制为仅一个用户ID。您可能需要使用此过滤器的where
子句。
答案 1 :(得分:2)
通常,对于平面类型表(如用户数据),这不是一个好习惯。此结构通常用于存储用户指定的自定义字段或元数据,其中单个实例可以没有或有数百个。
避免这种情况的原因是,如果你想获得N个用户属性,你必须在MySQL中进行N-1连接,并且可能在应用程序中动态生成查询,这是次优的。只需将所有标准数据放在一个表中,就可以将此user_field表用于仅在请求时检索的自定义字段。
如果您坚持使用此结构以便能够有效地进行查询,我会将user_field表更改为不具有auto_increment id,而是将user_id和key键为表的PRIMARY KEY。这样,用户的所有字段将在表空间中彼此相邻(假设您使用的是InnoDB),并且查找将是主键查找。另一个步骤是将密钥更改为tinyint并使用查找ID而不是实际字符(您甚至可以在代码中使用CONSTANTS使其更清晰)。
答案 2 :(得分: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'
答案 3 :(得分:0)
您想使用JOIN - 语句,并使用ID和user_id作为主题。
答案 4 :(得分: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
但这不是好方法。如果数据库变大,您将不得不在性能上妥协。你应该使用另一种设计模式。