SQL加入 - 需要单行

时间:2012-07-05 21:37:30

标签: php sql join left-join

我的MySQL表结构包含两个类似于以下内容的表:

UserId field1 field2
1       XXX    YYY
2       ABC    DDD
3       EEE    FFF
.
.
.
n       GGG    DDD


UserId  attribute
1        blah
1        adfadf 
1        ddad
2        adff
3        adfa
3        sdff
.
.
.
z        adss

表1每个ID只有1条记录。表2每个id有M个记录。表1和表2中的ID是相关的。我的查询类似于以下内容:

SELECT
    t1.`UserId`,
    t1.`field1`,
    t1.`field2`,
    t2.`attribute`
FROM `table1` AS `t1`
    LEFT JOIN `table2` AS `t2` ON `t1`.UserId = `t2`.UserId
WHERE t1.`UserId` = 3

查询返回以下内容:

3 EEE FFF adfa
3 EEE FFF sdff

我不想为每个记录返回重复记录。我想返回一行,比如

3 EEE FFF (adfa,sdff)

第4个字段是数据结构(数组?结果集?),它包含为给定用户标识返回的所有属性。

EDIT ::: 我看到许多涉及CONCAT的解决方案,将其转换为CSV。有逗号的字段会不会搞砸?

6 个答案:

答案 0 :(得分:1)

SELECT
    t1.`UserId`,
    t1.`field1`,
    t1.`field2`,
    CONCAT'(',GROUP_CONCAT(DISTINCT t2.`attribute`SEPARATOR ','),')') AS Attributes
FROM `table1` AS `t1`
    LEFT JOIN `table2` AS `t2` ON `t1`.UserId = `t2`.UserId
WHERE t1.`UserId` = 3
GROUP BY  t1.`UserId`,t1.`field1`,t1.`field2`

答案 1 :(得分:1)

我的评论摘要:

单个字段中唯一可以存在的数据结构是原始数据类型。

在这种情况下,最终使用逗号分隔的字符串是有意义的。你不能在那里放一个数组,你不能在那里嵌套数据集。正如您已有的那样,关系数据库可以实现您想要的多行数据。并且将多个值聚合到单个字段中被认为是关系数据库中非常痛苦的反模式。它使得数据以多种不同的方式进行查询变得很痛苦。

简而言之:

  • 单独行上的值= good
  • 将值合并为一个字段= bad

当前结构是关系数据库中的常规最佳实践,我绝不会推荐JSON_ENCODED字符串选项。我的建议是不要这样做,除非你有特殊的理由需要这样做。如果你有一个我会有兴趣知道它,因为我们可以评论这种方法是否真的有用。从长远来看,通常尝试做你要求的事情是没有用的。

根据您的示例,如果您有两个包含逗号的值,会发生什么?它只是在惹麻烦。


如果您真的担心不必要的网络流量,请分别从两个表中选择并在嵌套循环中处理它们。 *(只需确保两个数据集以相同的方式排序[在本例中为user_id],以使嵌套循环尽可能简单。)*

答案 2 :(得分:0)

不确定这是否适用于您的SQL变体。在T-SQL中,这可以通过引入局部变量来实现。这个小样本演示了。如果您不熟悉,“WITH”子句是一个“公用表表达式”,可以轻松地为我提供样本数据。

declare @temp as varchar(10);
select @temp = '';

with vals as (
    select '1' as a
    union select '2' as a
)
select @temp = @temp +  a + ','
from vals

select '(' + @temp + ')'

对于您的查询,只需将其更改为select @temp = @temp + attribute即可。当然,您需要添加一些子字符串代码来删除最后一个额外的逗号。

答案 3 :(得分:0)

如果您使用的是mysql,一种方法是使用GROUP_CONCAT

答案 4 :(得分:0)

如果您使用mysql,请尝试GROUP_CONCAT。如果这符合,请注意GROUP_CONCAT具有最大长度。您可以使用会话变量“group_concat_max_len”调整它。

答案 5 :(得分:0)

您需要使用group_concat运算符进行连接和分组:

SELECT t1.`UserId`, t1.`field1`, t1.`field2`,
       concat('(', group_concat(t2.`attribute`, ','), ')')
FROM `table1` `t1` LEFT JOIN
     `table2` AS `t2`
     ON `t1`.UserId = `t2`.UserId
WHERE t1.`UserId` = 3 
group by t1.`UserId`, t1.`field1`, t1.`field2`
相关问题