在核心语句的学习的基础之上,我们再来看如何使用SQL语句处理更复杂的分析问题。在实际工作中,掌握SQL的核心语句以及三种常见的进阶用法可以涵盖80%需要用到的SQL的工作。作为数据分析师,需要具备构建多层复杂逻辑语句的能力,在熟练使用SQL的基础上有意识地优化语句,进而简化工作流程更加高效的产出数据分析结果。
本节概要:
1.子查询
2.条件判断语句
3.SQL语句优化
学习目标 :
1.构建多层、复杂逻辑语句,简化工作流程来有效产出数据分析结果
2. 获得SQL语句优化意识,成为更高效、专业的分析师
(一)SQL进阶用法——子查询
子查询作用:构建复杂逻辑,简化需求解答过程
什么是子查询?
- 将一个查询语句用于构建另外一个查询语句的过滤条件或者数据源
- 用于构建复杂SQL语句来简化使用SQL解决问题的过程
用法:
1.子句是一个完整的SQL语句
2. 使用括号() 包围子句
3. 使用多重子语句解决复杂问题
DESCRIBE `产品信息`
__
产品号码 int(11)
产品名称 varchar(256)
供应商号码 int(11)
产品单价 decimal(12,2)
产品描述 varchar(256)
# 示例:单行单列过滤条件子查询
SELECT
*
FROM `产品信息`
WHERE `产品单价` >= 0.5 * (SELECT MAX('产品单价') as `最高单价` FROM `产品信息`)
子查询分类:
-
单行单列过滤条件子查询:子查询语句返回单行单列值作为结果
-
多行多列过滤条件子查询:子查询语句返回多行单列值作为结果
-
临表子查询:子查询语句返回临时列表(多行多列)作为结果
(1)单列过滤子查询
什么是单行单列过滤条件子查询?
- 子句仅返回单个值(一行一列的数据)作为运行结果
- 子句的记过用于后续SQL的过滤条件
为什么需要单行单列过滤条件子查询?
- 使用数据表中的数据来构建过滤条件
- 减少SQL运行步骤,简化解答问题的过程
——————
案例需求背景:
案例:列出所有产品单价高于或等于最高产品单价50%产品的详情信息
需求拆解:
- 最终返回结果:产品详细信息
- 过滤数据列:产品单价
- 过滤条件:高于或等于最高产品单价50%
确定数据位置:产品信息表
# 普通SQL语句解答过程和思路
## 第一步:查询产品最高售价,手动记录最高推荐售价
SELECT
MAX(`产品单价`) AS `最高单价`
FROM `产品信息`
## 第二步:使用记住的最高推荐售价构建SQL语句解答问题
SELECT *
FROM `产品信息` WHERE `产品单价` >= 0.5 *97
# 单行单列过滤条件子查询解答思路&过程
## 使用查询产品最高价作为子句来直接构建主句中的WHERE过滤条件
## 单个SQL语句解决问题
SELECT
*
FROM
`产品信息`
WHERE
`产品单价` >= 0.5 * ( SELECT MAX( `产品单价` ) AS '最高单价' FROM `产品信息` )
# 主查询语句/子查询语句
(2)多行多列过滤条件子查询
案例:列出所有广东省供应商供应的产品详情信息
需求拆解:
- 最终返回结果:产品详情信息
- 过滤数据列:供应商信息
- 过滤条件:广东省供应商
确定数据位置:
- 产品信息表
- 产品信息表中只有供应商号码,没有省份信息
- 供应商数据信息表
- 供应商信息表中含有供应商号码和省份信息
解决思路:使用多行单列子查询构建语句来过滤产品信息表中的数据
- 使用供应商信息表中省份的信息得到广东省供应商的供应商号码
- 得到的供应商号码是多行单列数据
SELECT
`供应商号码`
FROM `供应商信息` WHERE `省份`= '广东省'
——————————
供应商号码
1
3
10
11
...
________
# 使用多行单列子查询构建语句来过滤产品信息表中的数据
SELECT
*
FROM
`产品信息`
WHERE
`供应商号码` IN ( SELECT `供应商号码` FROM `供应商信息` WHERE `省份` = '广东省' )
(3) 临表子查询
介绍:
-
什么是临表子查询
- 子句的结果构成一个临时列表
- 临时列表用于后续的SQL语句临表子查询
-
为什么要进行临表子查询
- 在一个语句中完成多步计算逻辑
- 约束最终返回结果
案例需求背景: 列出产品数目最多的供应商号码
需求拆解:
- 最终返回结果:供应商号码
- 过滤数据:产品数目
- 过滤条件:最多
确认数据位置:
- 产品信息数据表
解决思路:
- 使用聚合(GROUP BY)以及聚合函数(COUNT)来计算供应商提供的产品数目
- 通过排序(ORDER BY)和 选取(LIMIT)可以得到产品数目最多的供应商号码和产品数目
- 要求SQL语句只返回供应商的号码
代码实现:
# 业务目标:列出产品数目最多的供应商号码
## 使用临时子查询语句选择供应商号码
### 使用聚合语句作为子语句与AS关键字创建临时列表 'a'
### 使用SELECT语句选择供应商号码
SELECT
`供应商号码`
FROM
(
SELECT
`供应商号码`,
COUNT(`产品号码`) AS `产品数目`
FROM `产品信息`
GROUP BY `供应商号码`
ORDER BY `产品数目` DESC
LIMIT 1
) AS a # Every derived table must have its own alias
子查询小结:
- 子查询作用:构建复杂逻辑,简化需求解答过程
- 单行单列过滤条件子查询:子查询语句返回单行单列值作为结果
- 多行单列过滤条件子查询语句:返回多行单列值作为结果
- 临表子查询: 子查询语句返回临时列表(多行多列)作为结果
(二)、SQL进阶用法——条件判断语句
介绍:
什么是条件判断?
- 如果…就…(例:客户总消费金额大于5000,该客户就是VIP客户)
- 在同一个条件判断语句中,可以有一个到多个判断条件
条件判断语句
CASE
WHEN 判断条件 THEN 判断结果
[WHEN 判断条件 THEN 判断结果]
ELSE 默认值
END
**案例:**根据各位顾客的总消费金额计算消费级别
第一步:确定需要的数据表(可以根据数据字典和E-R图找到需要的数据表)—— “订单信息表”
第二步:定义不同的消费级别
根据顾客总消费额所在的区间,计算顾客的消费级别:
消费区间 | 消费级别 |
---|---|
大于等于5000 | VIP3 |
2000到4999 | VIP2 |
1000到1999 | VIP1 |
小于1000 | 普通 |
第三步:撰写条件判断语句获得结果
# 计算顾客总消费金额
SELECT
`顾客号码`,
SUM( `消费金额` ) AS `总消费金额`
FROM
`订单信息`
GROUP BY
`顾客号码`
-------
顾客号码 总消费金额
1 4596.2
2 1402.95
3 7515.35
4 13806.5
5 26968.15
6 3239.8
————————————————
# 根据总消费
# 计算总消费金额
SELECT
`顾客号码`,
CASE
WHEN `总消费金额` >= 5000 THEN 'VIP3'
WHEN `总消费金额` >= 2000 THEN 'VIP2'
WHEN `总消费金额` >= 1000 THEN 'VIP1'
ELSE '普通'
END AS `消费级别`
FROM
( SELECT `顾客号码`, SUM( `消费金额` ) AS `总消费金额` FROM `订单信息` GROUP BY `顾客号码` ) AS a #Every derived table must have its own alias
------
顾客号码 消费级别
1 VIP2
2 VIP1
3 VIP3
4 VIP3
5 VIP3
注:条件判断语句常用于数据转换,基于现有数据创建新的数据列
(三)、SQL进阶用法 —— SQL语句优化
- 避免在查询语句中使用 * 返回所有数据
- 在过滤语句中,如有可能,使用BETWEEN而不是IN
- 在聚合语句中,优先使用WHERE语句过滤掉原数据表中的数据再聚合
- 在子查询语句中,尽量在最后执行(ORDER BY)