将三个实体视为学生,课程,科目 以下是协会 -
student has_many courses,
student has_many subjects.
现在我想使用mysql group_concat,主题名称和课程名称,在课程上左连接,在主题上左联接以及group_by student_id获取学生记录。
问题是group_concat('subjects.name') as subject_names
给了我重复的主题条目,但group_concat('students.name') as student_names
给出了唯一的名称。
为什么??
答案 0 :(得分:9)
2个左连接是通过每个学生的子行的笛卡尔积乘以行
实施例
course
个值=每个课程重复两次subject
个值=每个主题重复三次修复:
选项1:根据MySQL docs
使用GROUP_CONCAT(DISTINCT ...)
在MySQL中,您可以获得表达式组合的连接值。要消除重复值,请使用DISTINCT子句。
选项2:使用UNION ALL +派生表
SELECT
Student, MAX(CourseConcat), MAX(SubjectConcat)
FROM
(
-- 2 separate SELECTs here
.. student LEFT JOIN course ...
UNION ALL
.. student LEFT JOIN subjects...
) T
GROUP BY
Student
第二个选项可能更好,虽然更复杂,因为你有 less 中间行要用DISTINCT进行处理
答案 1 :(得分:0)
按照您的逻辑,group_concat('subjects.name') as subject_names
会为您提供重复的条目,因为每个学生可能有超过1个主题,因此您将获得subject
表上每个学生记录的重复记录,而{ {1}}(我猜)每位学生有1条记录。
答案 2 :(得分:0)
我知道我可能驾驶这个主题太过分了,但是因为搜索谷歌的答案已经指示我好几次了我想分享我的解决方案,因为有点复杂的类似问题。
gbn指出的GROUP_CONCAT(DISTINCT ...)
解决方案非常棒,直到你实际上有多个相等的值或几乎相同的值,如á和。
我从查询中遗漏了distinct关键字并用PHP解决了问题。如果你只需要区分á,那么简单array_unique
就可以了。
不幸的是,我没有那么幸运,我也有完全相同的价值,我需要保留。考虑从数据库查询group_concat
字段中返回的样本值分解为数组:
$values = array( 'Value1','Value1','Value2','Value2','Value2','Value2' );
现在以某种方式区分你要处理多少重复项。我做了以下事情:
$x=0;
$first = reset($values);
while($first === $values[$x]) $x++;
上述解决方案仅在您的实际第一个和第二个值永远不相同时起作用,在我的情况下是真的。如果不是你的情况,请找出其他方法来了解你正在处理多少重复项。 最后,在模数的帮助下取消设置所有额外的值:
foreach($values as $k => $v){
if($k%$x !== 0) unset($values[$k]);
}
多数民众赞成。现在打印$ values将为您提供:
Array
(
[0] => Value1
[2] => Value2
[4] => Value2
)