在没有Group_Concat的情况下将多行连接到一个

时间:2012-07-27 07:53:16

标签: mysql join row

如何将多行合并为一行不使用group concat

考虑我有如下表格:

表用户:

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

表meta:

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.

表metaproperty:

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

使用group concat,值为“school”和“address”的metaproperty不在不同的列中,但一列

我尝试加入两次,但是我觉得它不优雅

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

有更好的解决方案吗?

2 个答案:

答案 0 :(得分: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

答案很长

是的,该查询很难看,但问题不是查询而是数据库设计。您正在使用的设计称为entity-attribute-value(EAV)。尽可能避免使用EAV设计!无论何时使用EAV,您的所有查询都会变成多个连接怪物。如果您可以将每个值存储在同一行的单独列中,则会更容易。

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

答案 1 :(得分: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