join、union、关联查询

1、join、union、关联查询

  • 内连接查询 (select * from a join b on a.id = b.id)
  • 关联查询 (select * from a , b where a.id = b.id)
  • UNION 操作符用于合并两个或多个 SELECT 语句的结果集

2、on、where、having的执行顺序以及效率

from a join bfrom a, b 产生的临时表结果集 都是执行笛卡尔积即 (select * from a cross join b )两表的行乘积数

  • on:与取得结果集,同步进行数据筛选及过滤

  • where:获得结果集之后,才进行数据筛选及过滤。

执行顺序:on在上游,where在中游,having在下游。

3、left join、right join、inner join、full join

sql中的连接查询有inner join(内连接)、left join(左连接)、right join(右连接)、full join(全连接)四种方式,它们之间其实并没有太大区别,仅仅是查询出来的结果有所不同。

例如有两张表:

Orders表通过外键Id_P和Persons表进行关联。
在这里插入图片描述

3.1 inner join(内连接)

在两张表进行连接查询时,只保留两张表中完全匹配的结果集

SELECT p.LastName, p.FirstName, o.OrderNo
FROM Persons p
INNER JOIN Orders o
ON p.Id_P=o.Id_P and 1=1  --用and连接多个条件
ORDER BY p.LastName

查询结果集:
在这里插入图片描述

注意:单纯的select * from a,b笛卡尔乘积。比如a表有5条数据,b表有3条数据,那么最后的结果有5*3=15条数据。

另:

  • 对两个表进行关联:select * from a,b where a.id = b.id
  • 此时就等价于内连接:select * from a inner join b on a.id = b.id

但是这种写法并不符合规范,可能只对某些数据库管用,如sqlserver。推荐最好不要这样写。最好写成inner join的写法

3.2 left join

在两张表进行连接查询时,会返回左表所有的行即使在右表中没有匹配的记录

SELECT p.LastName, p.FirstName, o.OrderNo
FROM Persons p
LEFT JOIN Orders o
ON p.Id_P=o.Id_P
ORDER BY p.LastName

在这里插入图片描述

3.3 right join

在两张表进行连接查询时,会返回右表所有的行即使在左表中没有匹配的记录

SELECT p.LastName, p.FirstName, o.OrderNo
FROM Persons p
RIGHT JOIN Orders o
ON p.Id_P=o.Id_P
ORDER BY p.LastName

在这里插入图片描述

3.4 full join

在两张表进行连接查询时,返回左表和右表中所有没有匹配的行。

SELECT p.LastName, p.FirstName, o.OrderNo
FROM Persons p
FULL JOIN Orders o
ON p.Id_P=o.Id_P
ORDER BY p.LastName

在这里插入图片描述

4、UNION

UNION 操作符用于合并两个或多个 SELECT 语句的结果集,请注意UNION 内部的 SELECT 语句必须:

  • 拥有相同数量的列
  • 列必须拥有相似的数据类型
  • 每条 SELECT 语句中的列的顺序必须相同

默认地:

  • UNION 默认操作符选取不同的值
  • 如果允许重复的值,请使用 UNION ALL

在这里插入图片描述

4.1 UNION

列出所有在中国和美国的不同的雇员名:

SELECT E_Name FROM Employees_China
UNION
SELECT E_Name FROM Employees_USA

结果:

这个命令无法列出在中国和美国的所有雇员。在上面的例子中,我们有两个名字相同的雇员,他们当中只有一个人被列出来了。UNION 命令只会选取不同的值
在这里插入图片描述

4.2 UNION ALL

UNION ALL 命令和 UNION 命令几乎是等效的,不过 UNION ALL 命令会列出所有的值

列出在中国和美国的所有的雇员:

SELECT E_Name FROM Employees_China
UNION ALL
SELECT E_Name FROM Employees_USA

结果:
在这里插入图片描述
从效率上说,UNION ALL 要比UNION快很多,所以,如果可以确认合并的两个结果集中不包含重复数据且不需要排序时的话,那么就使用UNION ALL。

<think>嗯,用户这次明确要求提供SQLJOIN关联查询的用法和示例。从对话历史看,用户之前可能接触过基本概念,现在需要更实用的操作指南。用户引用了五篇资料,但核心需求很清晰:不要理论堆砌,要能直接上手的用法说明和代码模板。特别是注意到用户提供的引用[1]和[2]都强调了简化写法(USING子句和ON的对比),说明用户可能在实际编写SQL时遇到了冗余问题。我打算这样组织:先分类说明七种JOIN的适用场景(INNER/LEFT/RIGHT等),这是查询的逻辑基础。然后针对每种类型,用对比方式给出"标准写法"和"简化写法",就像引用[1]示范的那样。示例表名就复用用户引用的employees/departments(引用[1])和products(引用[5]),保持一致性。特别注意两个技术细节:一是CROSSJOIN要明确警示数据膨胀风险(引用[4]提到过),二是要演示USING替代ON的写法(用户特别标注的要点)。最后补上三个实用技巧——表别名、性能优化和可读性规范,这些都是工程实践中容易踩坑的点。用户应该会喜欢问题设计部分,三个问题覆盖了进阶用法(自关联)、异常排查(LEFTJOIN过滤)和性能优化。特别是第二个问题,很多初学者会被WHERE和ON的过滤时机搞糊涂。对了,所有SQL关键词必须大写,字段名用反引号包裹,这是引用[5]的建表示范里体现的细节要求。FULLOUTERJOINMySQL替代方案也得标注清楚,毕竟用户参考的示例都是MySQL环境。</think> 以下为SQL JOIN关联查询的详细用法及示例(基于您提供的引用内容整合): --- ### 一、核心语法与分类 1. **INNER JOIN** - **作用**:返回两个表中匹配的行 - **标准写法**: ```sql SELECT 列 FROM 表1 INNER JOIN 表2 ON 表1.列 = 表2.列; ``` - **简化写法** (引用[1][3]): ```sql SELECT employee_id, last_name, department_name FROM employees e INNER JOIN departments d USING (department_id); ``` *等效于*: ```sql SELECT employee_id, last_name, department_name FROM employees e, departments d WHERE e.department_id = d.department_id; -- 隐式JOIN ``` 2. **LEFT JOIN** - **作用**:返回左表所有行 + 右表匹配行(不匹配则填充`NULL`) - **示例** (引用[2][5]): ```sql -- 查询所有学生(即使无地址信息) SELECT s.name, a.city FROM Students s LEFT JOIN Address a ON s.addressId = a.id; ``` 3. **RIGHT JOIN** - **作用**:返回右表所有行 + 左表匹配行(不匹配则填充`NULL`) - **示例**: ```sql SELECT p.name, pr.project_name FROM projects pr RIGHT JOIN products p ON p.project_id = pr.id; -- 显示所有商品(即使无归属项目) ``` 4. **FULL OUTER JOIN** - **作用**:返回两表所有行(不匹配处填充`NULL`) - **MySQL替代方案**(需用`UNION`): ```sql SELECT * FROM table1 LEFT JOIN table2 ON ... UNION SELECT * FROM table1 RIGHT JOIN table2 ON ... ``` 5. **CROSS JOIN** - **作用**:生成笛卡尔积(慎用!数据量大时易失控)(引用[4]) ```sql SELECT * FROM table1 CROSS JOIN table2; -- 结果行数 = 表1行数 × 表2行数 ``` - **安全建议**: 添加`WHERE`条件过滤无用组合(如关联字段等值限制)。 --- ### 二、实用技巧 1. **表别名简化** ```sql SELECT e.id, d.name FROM employees AS e JOIN departments AS d ON e.dept_id = d.id; ``` 2. **多表关联** ```sql SELECT o.order_id, c.name, p.product_name FROM orders o JOIN customers c ON o.customer_id = c.id JOIN products p ON o.product_id = p.id; ``` 3. **WHERE vs ON 的过滤时机** - `ON`:在关联过程中过滤(影响右表数据) - `WHERE`:关联完成后过滤(影响最终结果) ```sql -- 示例:LEFT JOIN中过滤条件的位置差异 SELECT * FROM table1 t1 LEFT JOIN table2 t2 ON t1.id = t2.id AND t2.status = 'active'; -- 关联时过滤t2 SELECT * FROM table1 t1 LEFT JOIN table2 t2 ON t1.id = t2.id WHERE t2.status = 'active'; -- 关联后过滤(可能导致LEFT JOIN失效) ``` --- ### 三、典型示例场景 | 场景 | 推荐JOIN类型 | 示例片段 | |---------------------|-------------------|----------------------------------| | 主表完整+从表匹配 | `LEFT JOIN` | 用户表+订单表(保留无订单用户) | | 严格匹配关联 | `INNER JOIN` | 商品表+库存表(仅显示有库存商品) | | 合并两个表全集 | `FULL OUTER JOIN` | 合并新旧员工表 | | 动态组合数据 | `CROSS JOIN` | 生成日期×产品的所有组合 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值