【问题标题】:How to make dynamic multiple self joins?如何进行动态多个自连接?
【发布时间】:2021-08-15 02:11:24
【问题描述】:

为简化起见,假设我们有一张桌子供在特定时间完成某些课程的学生使用。考虑到一些学生可能有完整的时间null他们已经注册但尚未完成的一些课程。

student_id name course_name complete_time
1 Noah Database_L2 NULL
1 Noah Math_L1 2021-02-01
2 Luke Database_L2 2021-10-8
2 Luke Database_L1 2021-06-06
2 Luke Math_L1 2021-03-15
2 Luke Physics_L1 NULL
1 Noah Database_L1 2021-08-30

查询是查找完成给定课程序列的学生的姓名。 例如对于给定的序列:

  • (Math_L1,Database_L1)2 名学生完成了该序列(Noah 和 Luke)。
  • 仅限 (Math_L1、Database_L1、Database_L2) 1 名学生 (Luke)。

在给定任何序列的单个查询中如何做到这一点?

编辑:

  • 为简单起见,我们可以假设固定序列长度为 3

【问题讨论】:

  • 为简单起见,是否可以假设序列可以被硬编码/具有固定长度?
  • 当然。让我们假设序列长度为 3
  • 你应该在这里展示你自己的努力并告诉我们你卡在哪里了。在此示例中,您可以使用两个类的自联接(您已经在标题中提到)显示您的查询,然后告诉我们您不知道如何为可变数量的类扩展它。下次请展示你的努力。照原样,自联接不是解决方案,因为您必须为每个类添加联接,因此固定查询只能用于固定数量的类,如 user202729 建议的那样。如果您想要动态数量的类,则需要另一种方法。 (见我的回答。)

标签: mysql sql join self-join


【解决方案1】:

如果您想要这种动态的,即适用于任意数量课程的固定查询,您可以使用聚合和保存逗号分隔类的字符串。为此,此字符串必须采用固定格式,即类必须按字母顺序排列并用逗号分隔(并且不能有额外的空格)。

set @courses = 'Database_L1,Math_L1';

select name
from mytable
where find_in_set(course_name, @courses)
and complete_time <= now()
group by name
having group_concat(course_name order by course_name) = @courses
order by name;

演示:https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=45f43faf9fed09e79998717e9723d5df

如您所见,不需要自加入。我们只是按名称聚合,看看在查找请求的类时,我们是否会得到与请求相同的类列表字符串(即所有这些类都在字符串中)。

顺便说一下,我的查询将诺亚排除在结果之外,因为完成日(2021-08-30)是在未来。如果您想将未来的日期视为已完成(如果这些日期甚至可能出现在您的真实数据库中),则相应地更改 WHERE 子句(例如更改为 complete_time is not null)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-18
    • 1970-01-01
    • 1970-01-01
    • 2021-02-10
    • 1970-01-01
    • 2015-04-05
    相关资源
    最近更新 更多