如何使用正确的 GROUP_CONCAT 数据加入多个 SQL table 和 return 每个基本 table 记录一行?
How do I join with multiple SQL tables and return one row per base table record with the correct GROUP_CONCAT data?
我有一种情况,我想加入多个 SQL table 并在基础 table 和 GROUP_CONCAT
中为每条记录取回一行其他 table 数据以及 |
。不幸的是,使用我当前使用的查询方法,我在 GROUP_CONCAT
数据中返回了不需要的多重性,我不知道如何解决它。
我有以下基本数据库结构:
things
id | name
1 | Some Thing
2 | Some Other Thing
items
id | name
1 | Blob
2 | Starfish
3 | Wrench
4 | Stereo
users
id | name
1 | Alice
2 | Bill
3 | Charlie
4 | Daisy
things_items
thing_id | item_id
1 | 1
1 | 2
2 | 3
2 | 4
things_users
thing_id | user_id
1 | 1
1 | 2
1 | 3
2 | 4
理想情况下,我想编写一个查询,为 things
table 中的 Some Thing
行返回以下内容:
Some Thing | Blob|Starfish | Alice|Bill|Charlie
但是,我得到的结果如下:
Some Thing | Blob|Blob|Blob|Starfish|Starfish|Starfish | Alice|Alice|Bill|Bill|Charlie|Charlie
这是我正在使用的查询:
SELECT things.name,
GROUP_CONCAT(items.name SEPARATOR '|')
GROUP_CONCAT(users.name SEPARATOR '|')
FROM things
JOIN things_items ON things.id = things_items.thing_id
JOIN items ON things_items.item_id = items.id
JOIN things_users ON things.id = things_users.thing_id
JOIN users ON things_items.user_id = users.id
GROUP BY things.id;
我应该如何更改查询以按照我想要的方式取回数据并避免 GROUP_CONCAT
数据相乘?谢谢。
您正在沿着两个不同的维度串联。最简单的解决方案是 DISTINCT
:
SELECT t.name,
GROUP_CONCAT(DISTINCT i.name SEPARATOR '|')
GROUP_CONCAT(DISTINCT u.name SEPARATOR '|')
FROM things t JOIN
things_items ti
ON t.id = ti.thing_id JOIN
items i
ON ti.item_id = i.id JOIN
things_users tu
ON t.id = tu.thing_id JOIN
users u
ON tu.user_id = u.id
GROUP BY t.id;
请注意,以上过滤掉了没有项目或没有用户的东西。
如果每个事物都有少量项目和用户,则上述方法可以正常工作。随着数字的增长,性能会变差,因为它会为每个事物生成笛卡尔积。
加入前聚合即可解决:
SELECT t.name, i.items, u.users
FROM things t JOIN
(SELECT ti.thing_id, GROUP_CONCAT(i.name SEPARATOR '|') as items
FROM things_items ti JOIN
items i
ON ti.item_id = i.id
GROUP BY ti.thing_id
) i
ON t.id = ti.thing_id JOIN
(SELECT tu.user_id, GROUP_CONCAT(DISTINCT u.name SEPARATOR '|') as users
FROM things_users tu JOIN
users u
ON tu.user_id = u.id
GROUP BY tu.user_id
) tu
ON t.id = tu.thing_id ;
如果你想要所有的东西,甚至那些没有物品或名字的东西,你可以用 LEFT JOIN
替换外面的 JOIN
。
我有一种情况,我想加入多个 SQL table 并在基础 table 和 GROUP_CONCAT
中为每条记录取回一行其他 table 数据以及 |
。不幸的是,使用我当前使用的查询方法,我在 GROUP_CONCAT
数据中返回了不需要的多重性,我不知道如何解决它。
我有以下基本数据库结构:
things
id | name
1 | Some Thing
2 | Some Other Thing
items
id | name
1 | Blob
2 | Starfish
3 | Wrench
4 | Stereo
users
id | name
1 | Alice
2 | Bill
3 | Charlie
4 | Daisy
things_items
thing_id | item_id
1 | 1
1 | 2
2 | 3
2 | 4
things_users
thing_id | user_id
1 | 1
1 | 2
1 | 3
2 | 4
理想情况下,我想编写一个查询,为 things
table 中的 Some Thing
行返回以下内容:
Some Thing | Blob|Starfish | Alice|Bill|Charlie
但是,我得到的结果如下:
Some Thing | Blob|Blob|Blob|Starfish|Starfish|Starfish | Alice|Alice|Bill|Bill|Charlie|Charlie
这是我正在使用的查询:
SELECT things.name,
GROUP_CONCAT(items.name SEPARATOR '|')
GROUP_CONCAT(users.name SEPARATOR '|')
FROM things
JOIN things_items ON things.id = things_items.thing_id
JOIN items ON things_items.item_id = items.id
JOIN things_users ON things.id = things_users.thing_id
JOIN users ON things_items.user_id = users.id
GROUP BY things.id;
我应该如何更改查询以按照我想要的方式取回数据并避免 GROUP_CONCAT
数据相乘?谢谢。
您正在沿着两个不同的维度串联。最简单的解决方案是 DISTINCT
:
SELECT t.name,
GROUP_CONCAT(DISTINCT i.name SEPARATOR '|')
GROUP_CONCAT(DISTINCT u.name SEPARATOR '|')
FROM things t JOIN
things_items ti
ON t.id = ti.thing_id JOIN
items i
ON ti.item_id = i.id JOIN
things_users tu
ON t.id = tu.thing_id JOIN
users u
ON tu.user_id = u.id
GROUP BY t.id;
请注意,以上过滤掉了没有项目或没有用户的东西。
如果每个事物都有少量项目和用户,则上述方法可以正常工作。随着数字的增长,性能会变差,因为它会为每个事物生成笛卡尔积。
加入前聚合即可解决:
SELECT t.name, i.items, u.users
FROM things t JOIN
(SELECT ti.thing_id, GROUP_CONCAT(i.name SEPARATOR '|') as items
FROM things_items ti JOIN
items i
ON ti.item_id = i.id
GROUP BY ti.thing_id
) i
ON t.id = ti.thing_id JOIN
(SELECT tu.user_id, GROUP_CONCAT(DISTINCT u.name SEPARATOR '|') as users
FROM things_users tu JOIN
users u
ON tu.user_id = u.id
GROUP BY tu.user_id
) tu
ON t.id = tu.thing_id ;
如果你想要所有的东西,甚至那些没有物品或名字的东西,你可以用 LEFT JOIN
替换外面的 JOIN
。