1

我的 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 个字段是一个数据结构(数组?结果集?),它包含为给定用户 ID 返回的所有属性。

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

4

6 回答 6

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`
于 2012-07-05T21:45:08.710 回答
1

我的评论摘要:

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

在这种情况下,您最终使用逗号分隔的字符串是有意义的。您不能在其中放置数组,也不能在其中嵌套数据集。正如您已经拥有的那样,关系数据库通过多行数据完成您想要的工作。在关系数据库中,将多个值聚合到一个字段中被认为是一种非常痛苦的反模式。它使以多种不同方式查询数据变得痛苦。

简而言之:

  • 单独行上的单独值 = good
  • 将值组合成一个字段 = bad.

当前结构是关系数据库中的正常最佳实践,我永远不会推荐 JSON_ENCODED 字符串选项。我的建议是根本不要这样做,除非你有特殊的理由需要这样做。如果您确实有一个,我会很想知道它,因为我们可能会评论这种方法是否真的有用。从长远来看,通常尝试按照您的要求去做是没有帮助的。

根据您的示例,如果您有两个已经包含逗号的值会发生什么?这只是自找麻烦。


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

于 2012-07-05T21:57:39.913 回答
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. 当然,您需要添加一些子字符串代码来删除最后的额外逗号。

于 2012-07-05T21:44:04.170 回答
0

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

于 2012-07-05T21:44:05.823 回答
0

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

于 2012-07-05T21:44:29.393 回答
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`
于 2012-07-05T21:45:59.440 回答