有人可以用 JOIN 和 LEFT JOIN 帮助我理解以下 SQL 代码吗? (对 SQL 来说真的很新)

Posted

技术标签:

【中文标题】有人可以用 JOIN 和 LEFT JOIN 帮助我理解以下 SQL 代码吗? (对 SQL 来说真的很新)【英文标题】:Can someone help me to understand the following SQL code with JOIN and LEFT JOIN? (Really new to SQL) 【发布时间】:2020-04-30 16:05:29 【问题描述】:

有 3 个表:学生表、科目表和考试表。

Students table: 
+------------+--------------+
| student_id | student_name |
+------------+--------------+
|          1 | Alice        | 
|          2 | Bob          | 
|         13 | John         | 
|          6 | Alex         | 
+------------+--------------+

Subjects table: 
+--------------+
| subject_name | 
+--------------+
| Math         |
| Physics      |
| Programming  |
+--------------+

Examinations table: 
+------------+--------------+
| student_id | subject_name |
+------------+--------------+
|          1 | Math         |
|          1 | Physics      |   
|          1 | Programming  |   
|          2 | Programming  |   
|          1 | Physics      |   
|          1 | Math         |   
|         13 | Math         |   
|         13 | Programming  |   
|         13 | Physics      |   
|          2 | Math         |   
|          1 | Math         |   
+------------+--------------+

SQL代码如下:

SELECT s.student_id,s.student_name,b.subject_name,COUNT(e.subject_name) as attended_exams
FROM Students as s
INNER JOIN Subjects as b
LEFT JOIN Examinations as e
ON s.student_id=e.student_id AND b.subject_name=e.subject_name
GROUP BY s.student_id,b.subject_name;

我混淆的部分是INNER JOIN,因为学生表和主题表没有交集或公共列。我想我的目标是在执行LEFT JOIN 之前直观地理解/想象一张表格。由于我们已经在考试表中包含了所有科目,因此是否有必要包含科目表?真的很感谢帮助! 这实际上是 LeetCode 数据库的一个问题。链接如下: https://leetcode.com/problems/students-and-examinations/

【问题讨论】:

您的代码将在 Postgres 中返回错误,因为您有两个 joins 并且只有一个 on 子句。 @GordonLinoff 我选择了错误的选项卡。改成mysql了。感谢您指出。 大多数人不想为访问您的问题付费。您应该将其复制并粘贴到您的问题中。您的联接在任何形式的 SQL 中都不正确。我现在就写一个答案,不知道你的问题并从你的数据结构中假设一些事情。 这能回答你的问题吗? How to use mysql JOIN without ON condition? How to Ask help center 在考虑询问之前请先研究/google。阅读您正在使用的手册重新语法/功能。这也是一个(很明显)常见问题解答。对于代码问题,请提供minimal reproducible example。使您的帖子自成一体。每个帖子问 1 个问题。 PS你说你很困惑,但你不清楚是什么。例如,如果表“没有交集或公共列”怎么办?使用足够的单词、句子和对部分示例的引用。解释您的期望和/或就您没有得到的权威性陈述提出问题。 PSRe query meanings. 【参考方案1】:

你的查询相当于:

SELECT s.student_id, s.student_name, b.subject_name, 
       COUNT(e.subject_name) as attended_exams
FROM Students s CROSS JOIN
     Subjects b LEFT JOIN
     Examinations as e
     ON s.student_id = e.student_id AND 
        b.subject_name = e.subject_name
GROUP BY s.student_id, b.subject_name;

MySQL 扩展了JOIN 语法,因此ON 子句是可选的。就个人而言,我认为这是一个非常糟糕的主意。 CROSS JOINCROSS JOIN,应该这样指定。

查询的作用是为每个学生/学科组合生成一行。然后计算每个学生在每个科目中参加了多少次考试。

【讨论】:

【参考方案2】:

不需要带有主题表的JOIN。您可能还需要一个 IFNULL() 给 Alex,不幸的是他没有参加任何考试。

试试这个:

SELECT 
s.student_id, s.student_name, e.subject_name, IFNULL(COUNT(e.subject_name), 0) as attended_exams
FROM Students as s
LEFT JOIN Examinations as e
  ON s.student_id = e.student_id
GROUP BY s.student_id, e.subject_name
;

【讨论】:

Subjects 表中的所有数据都存在于Examinations 表中。无需进行涉及Subjects 表和CROSS JOIN 的低效查询。【参考方案3】:

正如雷纳托刚刚指出的那样,这是学生和学科之间的交叉连接。 其余的只是一种标记学生是否参加该科目考试的方法,因为COUNT 不会计算空值。

【讨论】:

【参考方案4】:

在 MySql 中,当使用joininner join 时,on 条件是可选的,如果未指定,则查询相当于交叉连接。更详细的解决方案here

【讨论】:

请不要回答重复的问题,标记/关闭它们作为重复。

以上是关于有人可以用 JOIN 和 LEFT JOIN 帮助我理解以下 SQL 代码吗? (对 SQL 来说真的很新)的主要内容,如果未能解决你的问题,请参考以下文章

SQL LEFT JOIN 不重复相同的行值

INNER JOIN 和 LEFT SEMI JOIN 的区别

Oracle left join 或right join

外连接(left join、full join、right join)与内连接(inner join)的区别

MySQL 的子查询和left join的比较,啥时候用子查询效率高,啥时候用left join效率高?

MySQL 数据库中 left outer join 和 left join 啥区别