1

如何在没有组 concat的情况下将多行加入一行?

考虑我有如下表:

表用户:

uid | name
-----------
 1  | A
 2  | B

表元:

uid | metaid | metaval
------------------------
 1  |   1    |  Jsep St.
 1  |   2    |  St. Oak No. 15
 2  |   1    |  Dt. San Joseph
 2  |   2    |  St. Oak No. 17
 2  |   3    |  OA.

表元属性:

metaid | metakey
-----------------
  1    | school
  2    | address 
  3    | dept
  4    | acc

我想用他们的学校和地址选择一个用户,所以查询是

SELECT 
    uid, name, metaval 
FROM user 
INNER JOIN meta ON meta.uid = user.uid 
WHERE meta.metaid = 1 OR meta.metaid = 2

它会输出

| UID | Name | MetaVal         |
--------------------------------
|  1  |  A   |  Jsep St.       |
|  1  |  A   |  St. Oak No. 15 |

我想要的结果是这样的

uid | name | school  |    address 
-------------------------------------
 1  |   A  | Jsep St.| St. Oak No. 15

使用组 concat,具有值“学校”和“地址”的元属性不在不同的列中,而是在一列中

我尝试加入两次并且它有效,但我认为它并不优雅

SELECT 
    uid, name, T1.metaval as school, T2.metaval as address 
FROM user 
INNER JOIN meta T1 ON T1.uid = user.uid AND T1.metaid = 1 
INNER JOIN meta T2 ON T2.uid = user.uid AND T2.metaid = 2

有更好的解决方案吗?

4

2 回答 2

1

有更好的解决方案吗?

简短的回答

不。

中等长度的答案

您的查询存在一些问题。

  • 你忘了包括user表格。
  • 格式化您的 SQL 以使其易于阅读。
  • LEFT JOIN如果某些数据可能丢失,请考虑使用。

试试这个:

SELECT uid, name, T1.metaval AS school, T2.metaval AS address
FROM user
LEFT JOIN meta T1 ON T1.uid = user.uid AND T1.metaid = 1
LEFT JOIN meta T2 ON T2.uid = user.uid AND T2.metaid = 2

长答案

是的,那个查询很难看,但问题不在于查询,而在于数据库设计。您正在使用的设计称为实体属性值(EAV)。尽可能避免使用 EAV 设计!每当您使用 EAV 时,您的所有查询都会变成多个连接怪物。如果您可以将每个值存储在同一行的单独列中,则会容易得多。

当然,在某些情况下您必须使用 EAV。然后你只需要接受你的查询会很长,难以阅读,不优雅和缓慢。这就是您为拥有灵活模式所做的权衡。

于 2012-07-27T08:02:33.620 回答
0

也许这是一个简短的答案:

SELECT uid, name,
       max(  case when meta.metaid = 1 then metaval  else '' end ) as school,
       max(  case when meta.metaid = 2 then metaval  else '' end ) as address
FROM user  
INNER JOIN meta 
    ON meta.uid = user.uid  
WHERE meta.metaid = 1 OR meta.metaid = 2 
group by uid, name
于 2012-07-27T09:31:18.227 回答