group_concat 在多重连接上工作不正确
group_concat works incorrect on multiple join
我在使用来自 3 tables 的连接和串联数据构建 select 请求时遇到问题。
第一个 table entity 有一些实体的 ID 及其作者:
id
author
11
"John"
12
"Mike"
13
"Kevin"
第二和第三 table 有与此实体相关的部分和文件,每行一行。任何实体的部分和文件计数都可以不同。
文件:
id
entity_id
file_name
1
11
file1
2
12
file1
3
12
file2
4
12
file3
5
13
file4
6
13
file5
7
13
file6
部分(有些实体也可以是 w/o 部分,例如本例中的 12):
id
entity_id
section_id
1
11
1001
2
11
1002
3
13
1003
我需要 select 来自实体的所有数据 table 将相关部分和文件连接为逗号分隔的字符串。为此,我创建了以下请求:
SELECT
entity.id,
entity.author,
group_concat(section.section_id) section_ids,
group_concat(file.file_name) files
FROM entity
LEFT JOIN file ON entity.id = file.entity_id
LEFT JOIN section ON entity.id = section.entity_id
group by entity.id;
我希望得到以下结果:
id
author
files
section_ids
11
"John"
file1
1001,1002
12
"Mike"
file1,file2,file3
null
13
"Kevin"
file4,file5,file6
1003
但实际上我得到了这个:
id
author
files
section_ids
11
"John"
file1,file1
1001,1002
12
"Mike"
file1,file2,file3
null
13
"Kevin"
file4,file5,file6
1003,1003,1003
当实体有多个部分时,看起来文件是重复的,而当实体有多个文件时,部分是重复的。
我尝试使用不同类型的连接(inner/outher、right/left)但没有找到任何解决方案。请帮我解决这个问题。
问题是当您在两个表中对给定实体进行多次匹配时:连接乘以行,聚合结果是错误的。
我会推荐预聚合。几个子查询应该可以很好地完成工作:
select e.id, e.author,
(select group_concat(f.file_name) from file f where f.entity_id = e.id) as files_names
(select group_concat(s.section_id) from section s where s.entity_id = e.id) as section_ids
from entity e
您正在连接两个不同的维度,从而产生笛卡尔积。对您的查询最简单的调整是 DISTINCT:
SELECT e.id, e.author,
group_concat(distinct s.section_id) as section_ids,
group_concat(f.file_name) as files
FROM entity e LEFT JOIN
file f
ON e.id = f.entity_id LEFT JOIN
section s
ON e.id = s.entity_id
group by e.id;
但是,为了性能,我会推荐 GMB 建议的方法。
我在使用来自 3 tables 的连接和串联数据构建 select 请求时遇到问题。
第一个 table entity 有一些实体的 ID 及其作者:
id | author |
---|---|
11 | "John" |
12 | "Mike" |
13 | "Kevin" |
第二和第三 table 有与此实体相关的部分和文件,每行一行。任何实体的部分和文件计数都可以不同。
文件:
id | entity_id | file_name |
---|---|---|
1 | 11 | file1 |
2 | 12 | file1 |
3 | 12 | file2 |
4 | 12 | file3 |
5 | 13 | file4 |
6 | 13 | file5 |
7 | 13 | file6 |
部分(有些实体也可以是 w/o 部分,例如本例中的 12):
id | entity_id | section_id |
---|---|---|
1 | 11 | 1001 |
2 | 11 | 1002 |
3 | 13 | 1003 |
我需要 select 来自实体的所有数据 table 将相关部分和文件连接为逗号分隔的字符串。为此,我创建了以下请求:
SELECT
entity.id,
entity.author,
group_concat(section.section_id) section_ids,
group_concat(file.file_name) files
FROM entity
LEFT JOIN file ON entity.id = file.entity_id
LEFT JOIN section ON entity.id = section.entity_id
group by entity.id;
我希望得到以下结果:
id | author | files | section_ids |
---|---|---|---|
11 | "John" | file1 | 1001,1002 |
12 | "Mike" | file1,file2,file3 | null |
13 | "Kevin" | file4,file5,file6 | 1003 |
但实际上我得到了这个:
id | author | files | section_ids |
---|---|---|---|
11 | "John" | file1,file1 | 1001,1002 |
12 | "Mike" | file1,file2,file3 | null |
13 | "Kevin" | file4,file5,file6 | 1003,1003,1003 |
当实体有多个部分时,看起来文件是重复的,而当实体有多个文件时,部分是重复的。 我尝试使用不同类型的连接(inner/outher、right/left)但没有找到任何解决方案。请帮我解决这个问题。
问题是当您在两个表中对给定实体进行多次匹配时:连接乘以行,聚合结果是错误的。
我会推荐预聚合。几个子查询应该可以很好地完成工作:
select e.id, e.author,
(select group_concat(f.file_name) from file f where f.entity_id = e.id) as files_names
(select group_concat(s.section_id) from section s where s.entity_id = e.id) as section_ids
from entity e
您正在连接两个不同的维度,从而产生笛卡尔积。对您的查询最简单的调整是 DISTINCT:
SELECT e.id, e.author,
group_concat(distinct s.section_id) as section_ids,
group_concat(f.file_name) as files
FROM entity e LEFT JOIN
file f
ON e.id = f.entity_id LEFT JOIN
section s
ON e.id = s.entity_id
group by e.id;
但是,为了性能,我会推荐 GMB 建议的方法。