用户表:
ID InstructionSets
1 123,124
指令集表:
ID Name
123 Learning SQL
124 Learning More SQL
期望的查询结果:
UserID SetID SetNames
1 123,124 Learning SQL,Learning More SQL
当前的SQL:
SELECT U1.ID AS UserID, U1.InstructionSets AS SetID, (
SELECT GROUP_CONCAT(Name ORDER BY FIELD(I1.ID, U1.InstructionSets))
FROM Instructions I1
WHERE I1.ID IN (U1.InstructionSets)
) AS SetName
FROM Users U1
WHERE `ID` = 1
结果
UserID SetID SetNames
1 123,124 Learning SQL
正如所料,如果我在子查询中删除WHERE子句,则会出现所有SetNames;但如果我指定了所需的ID,我只会获得与第一个ID相关联的名称。显然,我还需要以与ID相同的顺序获取SetNames。因此在GROUP_CONCAT中有ORDER BY。
也:
谢谢。
而不是像这样使用LIKE运算符:
SELECT U1.ID AS UserID, U1.InstructionSets AS SetID, (
SELECT GROUP_CONCAT(Name ORDER BY (I1.ID))
FROM Instructions I1
WHERE CONCAT(',', U1.InstructionSets, ',') LIKE concat('%,', I1.ID, ',%')
) AS SetName
FROM Users U1
WHERE `ID` = 1
见demo。 结果:
| UserID | SetID | SetName |
| ------ | ------- | ------------------------------ |
| 1 | 123,124 | Learning SQL,Learning More SQL |
我们可以使用FIND_IN_SET()
。在这种情况下,使用FIELD()
函数没有意义。
我们也可以在FIND_IN_SET()
条款中使用WHERE
。 (当在字符串列表中找不到字符串时,函数返回0。)
EG
SELECT u.id AS userid
, u.instructionsets AS setid
, ( SELECT GROUP_CONCAT(i.name ORDER BY FIND_IN_SET(i.id, u.instructionsets))
FROM `Instructions` i
WHERE FIND_IN_SET(i.id, u.instructionsets))
) AS setname
FROM `Users` u
WHERE u.id = 1
存储逗号分隔列表是一种反模式;一个单独的表不是矫枉过正。
假设id
在Users
表中是唯一的,我们可以用GROUP BY
进行连接操作
SELECT u.id AS userid
, MIN(u.instructionsets) AS setid
, GROUP_CONCAT(i.name ORDER BY FIND_IN_SET(i.id, u.instructionsets))) AS setname
FROM `Users` u
LEFT
JOIN `Instructions` i
ON FIND_IN_SET(i.id, u.instructionsets)
WHERE u.id = 1
GROUP BY u.id