SQL 多表连接
多数SQL查询只包含从一个或多个表中返回数据的单条SELECT语句。但是,SQL也允许执行多个查询(多条SELECT语句),并将结果作为一个查询结果集返回。这些组合查询通常称为并(union)或复合查询(compound query)
主要有两种情况需要使用联结
• 在一个查询中从不同的表返回结构数据;
• 对一个表执行多个查询,按一个查询返回数据。
提示:组合查询和多个WHERE条件多数情况下,组合相同表的两个查询所完成的工作与具有多个WHERE子句条件的一个查询所完成的工作相同。换句话说,任何具有多个WHERE子句的SELECT语句都可以作为一个组合查询. SQL最强大的功能之一就是能在数据查询的执行中联结(join)表。联结是利用SQL的SELECT能执行的最重要的操作,很好地理解联结及其语法是学习SQL的极为重要的部分。”
SELECT 课程号, 课程名 FROM course
UNION
SELECT 课程号, 课程名 FROM course1.
表的联结(join): 各表之间建立起联系,并最终联系在一起
交叉联结(cross join) 内联结(inner join) 左联结(left join) 右联结(right join) 全联结(full join)
表和表之间通过列产生关系.涉及到多个表查询用联结。
- 交叉联结(cross join):行数是两张表行数的笛卡尔积 类似于矩阵的运算规律
2. 内联结(inner join):查找出同时存在于两张表的数据;学生表和成绩表重合的地方是学号让两张表产生匹配,之后交叉联结;on表示两个表通过on后面的学号产生关系
3. 外联结(outter join)许多联结将一个表中的行与另一个表中的行相关联,但有时候需要包含没有关联行的那些行。与内联结关联两个表中的行不同的是,外联结还包括没有关联行的行。在使用OUTER JOIN语法时,必须使用RIGHT或LEFT关键字指定包括其所有行的表(RIGHT指出的是OUTER JOIN右边的表,而LEFT指出的是OUTER JOIN左边的表)。使用LEFT OUTER JOIN从FROM子句左边的表中选择所有行。为了从右边的表中选择所有行,需要使用RIGHT OUTER JOIN
练习
查询所有学生的学号、姓名、选课数、总成绩
SELECT s.学号, 姓名, SUM(成绩) AS 总成绩
FROM score AS s LEFT JOIN student AS st
ON( s.学号 = st.学号)
GROUP BY s.学号
ORDER BY SUM(成绩) DESC
查询平均成绩>70的所有学生的学号,姓名,平均成绩
SELECT
s.学号,
st.姓名,
AVG(成绩) AS 平均成绩
FROM
score AS s
LEFT JOIN student AS st ON ( s.学号 = st.学号 )
GROUP BY
s.学号
HAVING
AVG(成绩) >= 70
ORDER BY
AVG(成绩) DESC
查询学生的选课情况:学号,姓名,课程号,课程名称
SELECT
st.学号,
st.姓名,
c.课程号,
c.课程名
FROM
student AS st
JOIN score AS s ON ( st.学号 = s.学号 )
JOIN course AS c ON ( s.课程号 = c.课程号 )
查询每门课程的及格人数和不及格人数
SELECT s.课程号, c.课程名,
SUM(CASE WHEN s.成绩>=60 THEN 1 ELSE 0 END) AS 及格数,
SUM(CASE WHEN s.成绩<60 THEN 1 ELSE 0 END) AS 不及格数
FROM score AS s JOIN course AS c ON s.课程号 = c.课程号
GROUP BY s.课程号
UNION
SELECT s.课程号, c1.课程名,
SUM(CASE WHEN s.成绩>=60 THEN 1 ELSE 0 END) AS 及格数,
SUM(CASE WHEN s.成绩<60 THEN 1 ELSE 0 END) AS 不及格数
FROM score AS s JOIN course1 AS c1 ON s.课程号 = c1.课程号
GROUP BY s.课程号
使用分段来统计各科成绩,分别统计各分段人数,课程ID,课程名称
SELECT
s.课程号,
c.课程名,
SUM( CASE WHEN s.成绩 BETWEEN 85 AND 100 THEN 1 ELSE 0 END ) AS '[分段85-100]',
SUM( CASE WHEN s.成绩 BETWEEN 70 AND 84 THEN 1 ELSE 0 END ) AS '[分段70-84]',
SUM( CASE WHEN s.成绩 BETWEEN 60 AND 69 THEN 1 ELSE 0 END ) AS '[分段60-69]',
SUM( CASE WHEN s.成绩 < 60 THEN 1 ELSE 0 END ) AS 不及格
FROM
score AS s
JOIN course AS c ON s.课程号 = c.课程号
GROUP BY
s.课程号
UNION
SELECT
s.课程号,
c1.课程名,
SUM( CASE WHEN s.成绩 BETWEEN 85 AND 100 THEN 1 ELSE 0 END ) AS '[分段85-100]',
SUM( CASE WHEN s.成绩 BETWEEN 70 AND 84 THEN 1 ELSE 0 END ) AS '[分段70-84]',
SUM( CASE WHEN s.成绩 BETWEEN 60 AND 69 THEN 1 ELSE 0 END ) AS '[分段60-69]',
SUM( CASE WHEN s.成绩 < 60 THEN 1 ELSE 0 END ) AS 不及格
FROM
score AS s
JOIN course1 AS c1 ON s.课程号 = c1.课程号
GROUP BY
s.课程号
SQLZOO