左连接、右连接、自连接、内连接、全连接、NUION操作符
字段连接,行变换。
左连接与右连接
在MySQL数据库中,左连接(LEFT JOIN)和右连接(RIGHT JOIN)是两种不同类型的连接操作,它们用于将两个或多个表中的数据根据一定的条件结合起来。这两种连接操作的主要区别在于它们保留数据的方式。
-
左连接(LEFT JOIN):
-
左连接会返回左表(即
LEFT JOIN
语句中的第一个表)的所有记录,即使右表中没有匹配的记录。 -
如果右表中有匹配的记录,那么这些记录会被包含在结果集中。
-
如果右表中没有匹配的记录,那么结果集中右表的部分会用
NULL
填充。
示例 SQL 语句:
SELECT a.*, b.* FROM table1 a LEFT JOIN table2 b ON a.id = b.id;
-
-
右连接(RIGHT JOIN):
-
右连接会返回右表(即
RIGHT JOIN
语句中的第二个表)的所有记录,即使左表中没有匹配的记录。 -
如果左表中有匹配的记录,那么这些记录会被包含在结果集中。
-
如果左表中没有匹配的记录,那么结果集中左表的部分会用
NULL
填充。
示例 SQL 语句:
SELECT a.*, b.* FROM table1 a RIGHT JOIN table2 b ON a.id = b.id;
-
在实际应用中,左连接和右连接的使用取决于你希望保留哪个表的记录。通常,左连接用于保留主表(或左表)的所有记录,而右连接用于保留关联表(或右表)的所有记录。
左右连接理解
在MySQL中使用左连接(LEFT JOIN)时,如果右表(被连接的表)中有多个记录与左表(主表)中的一条记录相匹配,那么左连接的结果会为左表中的每一条记录生成多个行,每个行对应右表中的一个匹配记录。这意味着左表中的一条记录可能会在结果集中出现多次,每次出现都与右表中的一个不同的匹配记录相关联。
这种特性有时被称为“笛卡尔积”效果,因为左表的每一行都与右表中所有匹配的行组合。
例如,假设我们有两个表:
-
orders
表(左表)-
order_id
(订单ID) -
customer_id
(客户ID)
-
-
order_details
表(右表)-
order_detail_id
(订单详情ID) -
order_id
(订单ID) -
product_name
(产品名称)
-
如果一个订单(orders
表中的一条记录)有多个订单详情(order_details
表中的多条记录),使用左连接查询时,每个订单会与它的所有订单详情一起显示在结果集中。
SQL查询示例:
SELECT o.order_id, o.customer_id, d.product_name FROM orders o LEFT JOIN order_details d ON o.order_id = d.order_id;
如果订单ID为1的订单在orders
表中有一条记录,而在order_details
表中有三条与之匹配的记录,那么在结果集中,订单ID为1的记录将出现三次,每次对应一个不同的产品名称。
结果集可能如下所示:
order_id | customer_id | product_name ------------------------------------ 1 | 101 | Product A 1 | 101 | Product B 1 | 101 | Product C
在这个结果集中,订单ID为1的记录出现了三次,每次与不同的产品名称相关联。这就是左连接在右表中有多个匹配记录时的行为。
自连接
自连接(Self Join)是一种特殊的连接操作,它允许一个表与自身进行连接。自连接通常用于查询具有层次(树)或递归关系的数据,例如组织结构、层级关系、递归分类等。
在自连接中,同一个表被当作两个不同的表来使用,通常通过给表取别名来区分。连接条件通常涉及到表中的某个字段与另一个字段的比较。
示例
假设我们有一个名为 employees
的表,它包含员工的信息,包括每个员工的直接上级(manager_id
):
CREATE TABLE employees ( employee_id INT, employee_name VARCHAR(100), manager_id INT, dept_name VARCHAR(100) );
这个表中,employee_id
是员工的唯一标识,manager_id
是该员工直接上级的 employee_id
。我们可以通过自连接来查询每个员工及其直接上级的信息。
SQL 查询
以下是一个自连接的示例查询,用于找出每个员工及其直接上级的名字:
SELECT e1.employee_name AS 'Employee', e2.employee_name AS 'Manager' FROM employees e1 LEFT JOIN employees e2 ON e1.manager_id = e2.employee_id;
在这个查询中:
-
e1
是employees
表的第一个实例,代表员工。 -
e2
是employees
表的第二个实例,代表员工的直接上级。
结果解释
假设表中的数据如下:
employee_id | employee_name | manager_id | dept_name ----------------------------------------------- 1 | Alice | NULL | HR 2 | Bob | 1 | IT 3 | Carol | 1 | IT 4 | Dave | 2 | IT
查询结果将是:
Employee | Manager ----------------- Alice | NULL Bob | Alice Carol | Alice Dave | Bob
在这个结果中,Alice 没有直接上级,因为她的 manager_id
是 NULL
。其他员工的直接上级显示在 "Manager" 列中。
用途
自连接在处理具有层级或递归关系的数据时非常有用,例如:
-
组织结构图
-
产品分类
-
递归查询,如找到所有下属或所有上级
自连接是数据库查询中一个强大的工具,可以帮助你理解和操作复杂的数据关系。
内连接、全连接
需要注意的是,MySQL 也支持内连接(INNER JOIN),它只返回两个表中匹配的记录。此外,还有全连接(FULL JOIN),它返回左表和右表中的所有记录,但 MySQL 原生不支持全连接,可以通过联合左连接和右连接的结果来模拟全连接。
内连接(INNER JOIN)和全连接(FULL JOIN)是SQL中用于合并两个表的记录的两种不同的连接类型。下面我将通过具体的案例来解释这两种连接的区别和用法。
内连接(INNER JOIN)
内连接只返回两个表中匹配的记录。如果两个表中的连接条件不匹配,则不会返回结果。
案例
假设有两个表:students
和 courses
。
-
students
表:CREATE TABLE students ( student_id INT, student_name VARCHAR(100) );
数据:
student_id | student_name ------------------------- 1 | Alice 2 | Bob 3 | Carol
-
courses
表:CREATE TABLE courses ( course_id INT, course_name VARCHAR(100), student_id INT );
数据:
course_id | course_name | student_id ------------------------------------ 101 | Math | 1 102 | Science | 2 103 | History | 1
现在,如果我们想要找出选了课程的学生及其课程名称,可以使用内连接:
SELECT s.student_name, c.course_name FROM students s INNER JOIN courses c ON s.student_id = c.student_id;
结果:
student_name | course_name ----------------------- Alice | Math Bob | Science Alice | History
全连接(FULL JOIN)
全连接返回左表和右表中的所有记录。如果某一侧没有匹配的记录,则对应的列会用 NULL
填充。
案例
使用相同的 students
和 courses
表。
SQL 查询
MySQL 不直接支持 FULL JOIN
,但可以通过联合 LEFT JOIN
和 RIGHT JOIN
并使用 UNION
来模拟:
SELECT s.student_name, c.course_name FROM students s LEFT JOIN courses c ON s.student_id = c.student_id UNION SELECT s.student_name, c.course_name FROM students s RIGHT JOIN courses c ON s.student_id = c.student_id;
结果
student_name | course_name ----------------------- Alice | Math Bob | Science Alice | History Carol | NULL NULL | Math
在这个结果中:
-
Alice 和 Bob 出现在左侧和右侧的匹配结果中。
-
Carol 没有选任何课程,所以她的
course_name
为NULL
。 -
有一个课程没有学生选,所以
student_name
为NULL
。
总结
-
内连接:只返回匹配的记录,不匹配的记录不会出现在结果中。
-
全连接:返回所有记录,不匹配的记录用
NULL
填充。
全连接在处理需要同时考虑两个表所有记录的场景中非常有用,尤其是在需要分析两个表中所有数据的完整性时。
NUION操作符
UNION
是 SQL 中的一个操作符,用于合并两个或多个 SELECT
语句的结果集,并返回唯一的记录。UNION
会自动去除重复的行(整行),只保留唯一的结果。
基本语法
SELECT column1, column2, ... FROM table1 WHERE condition UNION SELECT column1, column2, ... FROM table2 WHERE condition
示例
假设有两个表:employees
和 managers
,我们想要合并这两个表中的所有员工信息。
-
employees
表:CREATE TABLE employees ( employee_id INT, employee_name VARCHAR(100), department VARCHAR(100) );
数据:
employee_id | employee_name | department --------------------------------------- 1 | Alice | IT 2 | Bob | HR
-
managers
表:CREATE TABLE managers ( manager_id INT, manager_name VARCHAR(100), department VARCHAR(100) );
数据:
manager_id | manager_name | department --------------------------------------- 3 | Carol | Finance 4 | Dave | Marketing
我们可以使用 UNION
来合并这两个表中的所有员工和经理的信息:
SELECT employee_id AS id, employee_name AS name, department FROM employees UNION SELECT manager_id, manager_name, department FROM managers;
结果:
id | name | department ------------------------- 1 | Alice | IT 2 | Bob | HR 3 | Carol | Finance 4 | Dave | Marketing
注意事项
-
列数匹配:使用
UNION
时,每个SELECT
语句中的列数必须相同。 -
列类型匹配:每个相应列的数据类型也必须兼容,例如,第一个查询的第二列是
VARCHAR
类型,那么第二个查询的第二列也应该是VARCHAR
类型。 -
去重:
UNION
会自动去除重复的行,只保留唯一的结果。如果你想要保留所有行(包括重复的行),可以使用UNION ALL
。
UNION ALL 示例
如果我们想要保留所有行,包括重复的行,可以使用 UNION ALL
:
SELECT employee_id AS id, employee_name AS name, department FROM employees UNION ALL SELECT manager_id, manager_name, department FROM managers;
如果 employees
和 managers
表中有重复的记录,UNION ALL
会保留这些重复的行。
总结
UNION
是一个非常有用的操作符,用于合并多个查询的结果集,并自动去除重复的行。使用 UNION ALL
可以保留所有行,包括重复的行。在实际应用中,根据需求选择合适的操作符。