MySQL单个语句合并两个表

时间:2013-07-15 10:52:56

标签: php mysql sql

我确信这已被提出/已经回答,但我不知道这种行为是如何被调用的,而且我的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中改变结果?

这是一个很好的数据库设计还是我应该放弃一个不同的(哪一个?)

5 个答案:

答案 0 :(得分:2)

您可以使用joingroup 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 

但这不是好方法。如果数据库变大,您将不得不在性能上妥协。你应该使用另一种设计模式。