📜  sql join 子查询 - SQL (1)

📅  最后修改于: 2023-12-03 15:35:04.517000             🧑  作者: Mango

SQL Join 子查询

在 SQL 中,JOIN 用于将两个或多个表中的行连接起来,以便我们可以通过从多个表中检索相关数据。而子查询,则是用一个 SQL 语句来获取其结果的查询语句。

通过将 JOIN 和子查询结合起来,可以实现更复杂的查询需求。本文将介绍在 SQL 中如何使用 JOIN 和子查询进行查询,以及一些常见的应用场景。

内连接

内连接是将两个表中至少有一列相同的行组合在一起,只返回两个表中存在的匹配行。

使用 JOIN 进行内连接的语法如下:

SELECT *
FROM table1
JOIN table2
ON table1.column_name = table2.column_name

其中 column_name 是两个表中有相同值的列。

另一种写法是使用 INNER JOIN

SELECT *
FROM table1
INNER JOIN table2
ON table1.column_name = table2.column_name

下面是一个内连接的例子。假设我们有两个表 studentsscores,其中 students 表有 idname 两列,而 scores 表有 idscore 两列。我们要查询学生的姓名和成绩,可以使用以下 SQL 语句:

SELECT students.name, scores.score
FROM students
JOIN scores
ON students.id = scores.id

这将输出以下结果:

| name | score | | ----- | ----- | | Alice | 95 | | Bob | 85 | | Carol | 92 |

左连接

左连接返回左侧表中所有的行,以及其在右侧表中的匹配行(如果有)。对于右侧表中没有匹配的行,将用 NULL 值填充。

使用 LEFT JOIN 进行左连接的语法如下:

SELECT *
FROM table1
LEFT JOIN table2
ON table1.column_name = table2.column_name

下面是一个左连接的例子。假设我们有一个表 departments 和一个表 employees,其中 departments 表有 idname 两列,而 employees 表有 idnamesalarydepartment_id 四列。我们要查询每个部门的名称和员工的姓名,可以使用以下 SQL 语句:

SELECT departments.name, employees.name
FROM departments
LEFT JOIN employees
ON departments.id = employees.department_id

这将输出以下结果:

| name | name | | -------------- | ------ | | Sales | Alice | | Sales | Bob | | Engineering | Carol | | Engineering | Dave | | Marketing | Ellen | | Marketing | Frank | | Human Resources | Gabrielle |

需要注意的是,由于没有员工在财务部门工作,因此输出显示出了 NULL 值。

右连接

右连接和左连接类似,但是返回右侧表中所有的行,以及其在左侧表中的匹配行(如果有)。对于左侧表中没有匹配的行,将用 NULL 值填充。

使用 RIGHT JOIN 进行右连接的语法如下:

SELECT *
FROM table1
RIGHT JOIN table2
ON table1.column_name = table2.column_name

下面是一个右连接的例子。假设我们有一个表 employees 和一个表 job_titles,其中 employees 表有 idnamesalaryjob_title_id 四列,而 job_titles 表有 idtitle 两列。我们要查询每个职务的职称和员工的姓名,可以使用以下 SQL 语句:

SELECT job_titles.title, employees.name
FROM job_titles
RIGHT JOIN employees
ON job_titles.id = employees.job_title_id

这将输出以下结果:

| title | name | | ----------------- | --------- | | Sales Manager | Alice | | Sales Associate | Bob | | Software Engineer | Carol | | Lead Engineer | Dave | | Marketing Manager | Ellen | | Marketing Associate | Frank | | NULL | Sarah |

需要注意的是,由于没有员工被分配到职务 NULL,因此输出显示出了 NULL 值。

子查询

子查询是在一个 SQL 语句中嵌套另一个 SQL 语句来获取其结果的查询语句。

子查询可以以多种方式使用,比如用作过滤条件或者用作连接条件。下面是一个使用子查询作为连接条件的例子。

假设我们有一个表 students,里面存储了学生的 ID、姓名和所在班级 ID:

| id | name | class_id | | ---- | ----- | -------- | | 1 | Alice | 1 | | 2 | Bob | 2 | | 3 | Carol | 1 | | 4 | Dave | 3 | | 5 | Ellen | 2 | | 6 | Frank | 3 |

我们还有一个表 classes,里面存储了班级的 ID 和人数上限:

| id | max_students | | ---- | ------------ | | 1 | 30 | | 2 | 25 | | 3 | 20 | | 4 | 30 |

我们要查询每个班级的实际学生人数和人数上限。首先要写一个查询语句,用于计算每个班级的实际学生人数:

SELECT class_id, COUNT(*) as num_students
FROM students
GROUP BY class_id

这将输出以下结果:

| class_id | num_students | | -------- | ------------ | | 1 | 2 | | 2 | 2 | | 3 | 2 |

接下来,我们要将这个子查询与 classes 表进行连接,将人数上限和实际学生人数组合在一起。可以使用以下 SQL 语句:

SELECT classes.id, classes.max_students, num_students
FROM classes
LEFT JOIN (
  SELECT class_id, COUNT(*) as num_students
  FROM students
  GROUP BY class_id
) as counts
ON classes.id = counts.class_id

这将输出以下结果:

| id | max_students | num_students | | ---- | ------------ | ------------ | | 1 | 30 | 2 | | 2 | 25 | 2 | | 3 | 20 | 2 | | 4 | 30 | NULL |

需要注意的是,在这个查询中使用了一个子查询来计算每个班级的实际学生人数。子查询被嵌套在 LEFT JOIN 语句中,并且 as counts 操作将子查询命名为 counts

结论

使用 JOIN 和子查询,可以更有效地查询和组合数据。内连接可用于查找两个表之间的匹配行,左连接可用于查找左侧表中的所有行,右连接可用于查找右侧表中的所有行。使用子查询,可以将查询的结果嵌套在另一个查询中,以便获取更精细的查询结果。无论是在开发 Web 应用程序,还是处理企业数据,JOIN 和子查询都是 SQL 程序员必须掌握的重要技能。