用户表
id u_id name phone email
1 912 abcd 23424 abcd@email.com
2 913 xyz 45342 xyz@email.com
3 916 pqrt 23239 wdiw@email.com
主题表
s_id name
1 eng
2 math
3 phy
城市表
c_id name
1 city1
2 city2
3 city3
位置表
l_id name
1 loc1
2 loc2
3 loc3
user_to_subject表
u_id s_id
913 2
913 3
user_to_city表
u_id c_id
913 1
913 3
user_to_location表
u_id l_id
913 2
913 3
我想要做的是选择一个包含完整细节的陈述,这就是我所尝试过的。
SELECT U.*, GROUP_CONCAT(S.`name`) AS subject, GROUP_CONCAT(C.`name`) AS class, GROUP_CONCAT(L.`name`) AS location FROM `user` U INNER JOIN `user_to_subject` UTS ON U.`u_id`=UTS.`u_id` INNER JOIN `subjects` S ON S.`s_id`=UTS.`s_id` INNER JOIN `user_to_class` UTC ON U.`u_id`=UTC.`u_id` INNER JOIN `city` C ON C.`c_id`=UTC.`c_id` INNER JOIN `user_to_location` UTL ON U.`u_id`=UTL.`u_id` INNER JOIN `location` L ON L.`l_id`=UTL.`l_id` WHERE U.`u_id`=913
我有重复的主题,城市和位置。不知道我在这里做错了什么。
答案 0 :(得分:0)
在您的情况下,最简单的解决方案是使用group_concat(distinct)
:
SELECT U.*,
GROUP_CONCAT(DISTINCT S.`name`) AS subject,
GROUP_CONCAT(DISTINCT C.`name`) AS class,
GROUP_CONCAT(DISTINCT L.`name`) AS location
FROM `user` U INNER JOIN
`user_to_subject` UTS
ON U.`u_id` = UTS.`u_id` INNER JOIN
`subjects` S
ON S.`s_id` = UTS.`s_id` INNER JOIN
`user_to_class` UTC
ON U.`u_id` = UTC.`u_id` INNER JOIN
`city` C
ON C.`c_id` = UTC.`c_id` INNER JOIN
`user_to_location` UTL
ON U.`u_id` = UTL.`u_id` INNER JOIN
`location` L
ON L.`l_id`=UTL.`l_id`
WHERE U.`u_id` = 913;
这不是最通用的解决方案,因为它会将所有中间结果生成为笛卡尔积(对于每个用户)。因此,如果您有2个类,3个位置和4个城市,则会生成24个中间行。
对于此查询,24行不是问题。但是,如果你有200个班级,300个地点和400个城市,那么中间结果会更大一些。最通用的解决方案是预先聚合结果或使用相关子查询。
此外,如果您希望保留缺少一个或多个属性的用户,您可能需要LEFT JOIN
而不是INNER JOIN
。