1

我确定这已经被询问/回答了,但我不知道如何调用这种操作并且我的 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”的附加条目,我会在最后一个结果中得到一个新列

这甚至可能仅在 MySQL 中还是我必须去更改 PHP 中的结果?

这甚至是一个好的数据库设计,还是我应该放弃它,换一个不同的(哪一个?)

4

5 回答 5

2

通常这不被认为是扁平类型表(如用户数据)的好习惯。此结构通常用于存储用户指定的自定义字段或元数据,您可以在单个实例中没有或数百个。

避免这种情况的原因是,如果您想获得 N 个用户属性,您必须在 MySQL 中进行 N-1 次连接,并且可能会在应用程序中动态生成次优查询。只需将所有标准数据放在一个表中,您就可以将此 user_field 表用于仅应请求检索的自定义字段。

如果您坚持使用这种结构以便能够有效地进行查询,我会将 user_field 表更改为没有 auto_increment id,而是将 user_id 设置为表的 PRIMARY KEY。这样,用户的所有字段最终将在表空间中彼此相邻(假设您使用的是 InnoDB),并且查找将是主键查找。进一步的步骤是将键更改为 tinyint 并使用查找 ID 而不是实际字符(您甚至可以在代码中使用 CONSTANTS 以使其更清晰)。

于 2013-07-15T11:14:53.753 回答
2

你可以用 ajoin和 a做到这一点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带有此过滤器的子句。

于 2013-07-15T10:56:56.137 回答
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'
于 2013-07-15T10:58:21.170 回答
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 

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

于 2013-07-15T11:10:52.533 回答
0

您想使用JOIN语句并使用 ID 和 user_id 作为主题。

于 2013-07-15T10:55:41.300 回答