两个不同表上的 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 在第二个表上给出重复的结果的主要内容,如果未能解决你的问题,请参考以下文章

python 两个链表的第一个公共结点

删除左表上的重复项,同时在右表SELECT JOIN上保留重复项

如果在第二个表上没有找到记录,则显示所有行为 0

在android中的不同活动中设置按钮上的时间

多个表上的mysql group_concat

在第二个文件中的列之后添加一个文件中的列,同时考虑到这两个文件具有不同的列数