两个不同表上的 group_concat 在第二个表上给出重复的结果
Posted
技术标签:
【中文标题】两个不同表上的 group_concat 在第二个表上给出重复的结果【英文标题】:group_concat on two different tables gives duplicate result on second table 【发布时间】:2012-03-25 01:51:04 【问题描述】:考虑三个实体作为学生、课程、学科 以下是关联 -
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
给出了唯一的名称。
为什么??
【问题讨论】:
【参考方案1】:我知道我可能有点离题了,但是因为从谷歌搜索答案已经多次将我指引到这里,所以我想分享我的解决方案,以解决更复杂的类似问题。
gbn 指出的GROUP_CONCAT(DISTINCT ...)
解决方案非常棒,直到您实际上有多个相等的值或几乎相等,例如 á 和 a。
我从查询中省略了 distinct 关键字,并用 php 解决了这个问题。如果您只需要区分 á 和 a,简单的 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
)
【讨论】:
【参考方案2】:两个左连接通过子行的笛卡尔积乘以行每个学生
例子
学生 1 有 3 门课程和 2 门科目 为学生 1 生成 6 行 为每个科目提供一个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 处理
【讨论】:
感谢您的详细回答。现在了解了两个不同表上的内部 group_concat 是如何工作的。【参考方案3】:按照您的逻辑,group_concat('subjects.name') as subject_names
会为您提供重复的条目,因为每个学生可能有不止 1 个科目,因此您会在 subject
表中获得每个学生记录的重复记录,而 group_concat('students.name') as student_names
(我假定)每个学生有 1 条记录。
【讨论】:
实际上不是 .. 我在 has_many 关系中没有任何重复条目。总是有与学生相关的独特学科和课程。以上是关于两个不同表上的 group_concat 在第二个表上给出重复的结果的主要内容,如果未能解决你的问题,请参考以下文章