前言:
作为一名数据分析的小白,最近学习和了解了数据分析中SQL入门相关的一些知识,在这篇博客中我将用通俗易懂的方式来与大家分享这几天我的所见所学。也希望能帮助到目前正在学习SQL的你,当然,如若文章存在错误之处请多指正!
目录
2. 不等于( != 或 <> )→ 排除 :排除类别为水果的商品信息
3. dense_rank() → 密集排名(允许并列,但排名连续)
一、为什么SQL是数据分析的必备技能
-
数据查询的行业标准(90%企业数据库使用SQL)
-
数据提取/清洗/聚合的核心工具
-
与Python/R等工具配合的桥梁作用等
二、数据分析入门需要掌握的相关SQL知识
作为一名数据分析师,在平时接触的业务中,使用SQL的场景往往是:查
所以数据的写入、修改、删除、存储,事务控制,角色、安全管理,查询速度的优化等我们可以不用详细掌握。
而我们入门大致需要掌握以下内容:
-
select与from
-
数据提取/清洗/聚合的核心工具
-
与Python/R等工具配合的桥梁作用等
select与from:
🧩 select与from 是什么?
select它用于拿取你指定的信息,from负责数据从哪里来。
🌰 基础数据表
假设有一张商品表 products
:
id | 商品名 | 价格 | 库存 |
---|---|---|---|
1 | 苹果 | 5 | 100 |
2 | 香蕉 | 3 | 80 |
3 | 橙子 | 4 | 120 |
select → 拿商品的相关信息(如商品id、名称、价格、库存)
from → 从哪个地方拿(从哪张表取数据)
🎯 基本用法:
select 字段名(要拿的商品的相关信息)
from 表名(数据从哪个表来)
1:我要拿取全部的商品的名称与价格:
代码:
select 商品名,价格
from products
结果:
商品名 | 价格 |
---|---|
苹果 | 5 |
香蕉 | 3 |
橙子 | 4 |
2:我要拿取全部商品的全部信息:
代码:
select *
from products
这里的*代表选取表格所有列(也就是商品的所有信息)
结果:
id | 商品名 | 价格 | 库存 |
---|---|---|---|
1 | 苹果 | 5 | 100 |
2 | 香蕉 | 3 | 80 |
3 | 橙子 | 4 | 120 |
where
🧩 WHERE 是什么?
它是 SQL 中的条件筛选器,帮你从表中只挑出符合条件的数据。
🌰 基础数据表
假设商品表 products
如下:
id | 商品名 | 价格 | 库存 | 类别 |
---|---|---|---|---|
1 | 苹果 | 5 | 100 | 水果 |
2 | 香蕉 | 3 | 80 | 水果 |
3 | 橙子 | 4 | 120 | 水果 |
4 | 土豆 | 2 | 200 | 蔬菜 |
5 | 可乐 | 6 | 150 | 饮料 |
where→ 筛选符合条件的商品的相关信息(如价格>4元的商品,库存>100的商品)
🎯 WHERE 的 6 大核心用法:
1. 等于(=)→ 精确匹配:挑选出类别为水果的商品信息
select *
from products
where 类别='水果' --注意文本用单引号
结果1:
id | 商品名 | 价格 | 库存 | 类别 |
---|---|---|---|---|
1 | 苹果 | 5 | 100 | 水果 |
2 | 香蕉 | 3 | 80 | 水果 |
3 | 橙子 | 4 | 120 | 水果 |
2. 不等于( != 或 <> )→ 排除 :排除类别为水果的商品信息
select *
from products
where 商品名!='水果' --也可以用<>
结果2:
id | 商品名 | 价格 | 库存 | 类别 |
---|---|---|---|---|
4 | 土豆 | 2 | 200 | 蔬菜 |
5 | 可乐 | 6 | 150 | 饮料 |
3. 比较运算符 → 数值筛选:筛选价格大于4元的商品信息
select *
from products
where 价格 > 4
结果3:
id | 商品名 | 价格 | 库存 | 类别 |
---|---|---|---|---|
1 | 苹果 | 5 | 100 | 水果 |
5 | 可乐 | 6 | 150 | 饮料 |
其他运算符:
-
>
大于 -
<
小于 -
>=
大于等于 -
<=
小于等于
4. 范围查询 → between / in:
① between → 区间筛选:筛选价格在3-5元间的商品信息
select *
from products
where 价格 between 3 and 5
结果4-①:
id | 商品名 | 价格 | 库存 | 类别 |
---|---|---|---|---|
1 | 苹果 | 5 | 100 | 水果 |
2 | 香蕉 | 3 | 80 | 水果 |
3 | 橙子 | 4 | 120 | 水果 |
② in → 多值匹配:筛选名为可乐或苹果的商品:
select *
from products
where 商品名 in ('可乐','苹果')
结果4-② :
id | 商品名 | 价格 | 库存 | 类别 |
---|---|---|---|---|
1 | 苹果 | 5 | 100 | 水果 |
5 | 可乐 | 6 | 150 | 饮料 |
5. 模糊查询 → like:查询以果字结尾的商品信息
select *
from products
where 商品名 like '%果'
结果5:
id | 商品名 | 价格 | 库存 | 类别 |
---|---|---|---|---|
1 | 苹果 | 5 | 100 | 水果 |
用通配符匹配部分文本:
-
%
代表任意多个字符,可以是0个,1个,2个,n个 -
_
代表一个字符
6. 逻辑组合 → and / or / not
① and → 同时满足多个条件:查询类别为水果并且价格小于5元的商品信息
select *
from products
where 类别='水果' and 价格 < 5
结果6-①:
id | 商品名 | 价格 | 库存 | 类别 |
---|---|---|---|---|
2 | 香蕉 | 3 | 80 | 水果 |
3 | 橙子 | 4 | 120 | 水果 |
② or → 满足任意一个条件:查询类别为水果或者库存大于150的商品信息
select *
from products
where 类别='水果' or 库存 > 150
结果6-②:
id | 商品名 | 价格 | 库存 | 类别 |
---|---|---|---|---|
1 | 苹果 | 5 | 100 | 水果 |
2 | 香蕉 | 3 | 80 | 水果 |
3 | 橙子 | 4 | 120 | 水果 |
4 | 土豆 | 2 | 200 | 蔬菜 |
③ not → 取反:查询类别不是水果的商品信息
select *
from products
where not 类别='水果'
结果6-③:
id | 商品名 | 价格 | 库存 | 类别 |
---|---|---|---|---|
4 | 土豆 | 2 | 200 | 蔬菜 |
5 | 可乐 | 6 | 150 | 饮料 |
补充 distinct (去重)用法:
select distinct 类别
from products
结果:
类别 |
---|
水果 |
蔬菜 |
饮料 |
⚠️ 注意事项
-
文本必须加引号:
where 类别 = '水果'
(正确) vs where类别 = 水果
(错误) -
null 值判断:要用
is null
,不能用= null
where 类别 is null
-
大小写敏感:部分数据库区分大小写(如
'apple'
和'Apple'
可能不同) -
运算符优先级:and 优先级高于 or,建议用括号明确逻辑
where ( 条件1 or 条件2 ) and 条件3
order by
🧩 order by 是什么?
它是 SQL 中的「排序小助手」,帮你把查询结果按照你想要的顺序排列。
比如:
-
按价格从低到高排列商品
-
按库存从多到少排列
-
先按类别排序,再按价格排序
🌰 基础数据表
假设商品表 products
如下:
id | 商品名 | 价格 | 库存 | 类别 |
---|---|---|---|---|
1 | 苹果 | 5 | 100 | 水果 |
2 | 香蕉 | 3 | 80 | 水果 |
3 | 橙子 | 4 | 120 | 水果 |
4 | 土豆 | 2 | 200 | 蔬菜 |
5 | 可乐 | 6 | 150 | 饮料 |
🎯order by 的 3 种核心用法:
1. 单列升序排序 → 按价格从低到高:
select *
from products
order by 价格
结果:
id | 商品名 | 价格 | 库存 | 类别 |
---|---|---|---|---|
4 | 土豆 | 2 | 200 | 蔬菜 |
2 | 香蕉 | 3 | 80 | 水果 |
3 | 橙子 | 4 | 120 | 水果 |
1 | 苹果 | 5 | 100 | 水果 |
5 | 可乐 | 6 | 150 | 饮料 |
解释:
-
asc
(升序)是从小到大,可以省略不写 -
desc
(降序)是从大到小
2. 单列降序排序 → 按库存从多到少:
select *
from products
order by 库存 desc
结果:
id | 商品名 | 价格 | 库存 | 类别 |
---|---|---|---|---|
4 | 土豆 | 2 | 200 | 蔬菜 |
5 | 可乐 | 6 | 150 | 饮料 |
3 | 橙子 | 4 | 120 | 水果 |
1 | 苹果 | 5 | 100 | 水果 |
2 | 香蕉 | 3 | 80 | 水果 |
3. 多列排序 → 先按类别排序,再按价格降序:
select *
from products
order by 类别 asc,价格 desc
结果:
id | 商品名 | 价格 | 库存 | 类别 |
---|---|---|---|---|
5 | 可乐 | 6 | 150 | 饮料 |
4 | 土豆 | 2 | 200 | 蔬菜 |
1 | 苹果 | 5 | 100 | 水果 |
3 | 橙子 | 4 | 120 | 水果 |
2 | 香蕉 | 3 | 80 | 水果 |
解释:
-
先按类别升序排列(饮料→蔬菜→水果)
-
同一类别内,按价格从高到低排列(苹果5 > 橙子4 > 香蕉3)
⚠️ 注意事项
-
默认是升序:
order by 价格
等价于order by 价格 asc
-
处理NULL值:null 在排序中通常会被当作最小值(升序排在最前,降序排在最后)
select * from products order by 价格 desc nulls last
-
性能问题:
-
对大数据量排序时可能变慢,尽量搭配
limit
使用 -
如果经常需要排序,可以对字段建索引
-
-
别名排序:可以用select中的别名
select 价格 as price from products order by price desc
聚合函数
🧩 聚合函数是什么?
它们是 SQL 的「计算器」,专门对一组数据做汇总计算。
核心功能:
-
对多行数据进行统计
-
返回单个结果值
🌰 基础数据表
假设有一张 sales
表记录每日销售数据:
日期 | 商品类别 | 销售额 |
---|---|---|
2023-08-01 | 水果 | 500 |
2023-08-01 | 蔬菜 | 300 |
2023-08-02 | 水果 | 600 |
2023-08-02 | 蔬菜 | 400 |
2023-08-03 | 水果 | 450 |
🎯 五大常用聚合函数
1. sum() → 求和:
select sum(销售额) 总销售额
from sales
结果:
总销售额 |
---|
2250 |
计算过程:
500 + 300 + 600 + 400 + 450 = 2250
2. avg() → 平均值
场景:计算平均每日销售额
select avg(销售额) 平均销售额
from sales
结果:
平均销售额 |
---|
450 |
计算过程:
(500 + 300 + 600 + 400 + 450) / 5 = 450
3. count() → 计数
场景:统计销售记录条数
select count(*) 记录条数
from sales
结果:
记录条数 |
---|
5 |
注意:
-
count(*)
统计所有行(包括 null) -
count(字段)
统计非 null 的行
4. max() → 最大值
场景:找出最高销售额
select max(销售额) 最高销售额
from sales
结果:
最高销售额 |
---|
600 |
5. MIN() → 最小值
场景:找出最低销售额
select min(销售额) 最低销售额
from sales
结果:
最低销售额 |
---|
300 |
⚠️ 注意事项
-
sum()
、avg()
、max()
、min()
忽略 null -
count(字段)
忽略 null,count(*)
不忽略 -
对大数据量聚合时可能变慢,尽量结合索引使用
group by
🧩 group by 是什么?
它是 SQL 中的「分类整理员」,把数据按指定字段分组后分别计算。
核心功能:
-
按某个字段(或多个字段)分组
-
对每组数据进行聚合计算(一般结合聚合函数使用)
🌰 基础数据表
假设有一张 sales
表记录每日销售数据:
日期 | 商品类别 | 销售额 |
---|---|---|
2023-08-01 | 水果 | 500 |
2023-08-01 | 蔬菜 | 300 |
2023-08-02 | 水果 | 600 |
2023-08-02 | 蔬菜 | 400 |
2023-08-03 | 水果 | 450 |
🎯 group by 的核心用法
1. 单字段分组:
场景:按商品类别统计总销售额
select 商品类别,sum(销售额) 类别总销售额
from sales
group by 商品类别
结果:
商品类别 | 类别总销售额 |
---|---|
水果 | 1550 |
蔬菜 | 700 |
水果总额=500+600+450
蔬菜总额=300+400
2. 多字段分组
场景:按日期和商品类别统计销售额
select 日期, 商品类别,sum(销售额)日销售额
from sales
group by 日期,商品类别
结果:
日期 | 商品类别 | 日销售额 |
---|---|---|
2023-08-01 | 水果 | 500 |
2023-08-01 | 蔬菜 | 300 |
2023-08-02 | 水果 | 600 |
2023-08-02 | 蔬菜 | 400 |
2023-08-03 | 水果 | 450 |
⚠️ 注意事项
-
select 的字段限制:
-
使用
group by
后,select
只能包含:-
group by
的字段 -
聚合函数
-
-
-
null 值处理:
-
group by
会把 null 值分到同一组
-
-
性能问题:
-
对大数据量分组时可能变慢,尽量结合索引使用
-
having
🧩 having 是什么?
它是 SQL 中的「分组质检员」,专门筛选符合条件的分组结果。
核心功能:
-
对
group by
分组后的结果进行过滤 -
通常与聚合函数一起使用
🌰 基础数据表
假设有一张 sales
表记录每日销售数据:
日期 | 商品类别 | 销售额 |
---|---|---|
2023-08-01 | 水果 | 500 |
2023-08-01 | 蔬菜 | 300 |
2023-08-02 | 水果 | 600 |
2023-08-02 | 蔬菜 | 400 |
2023-08-03 | 水果 | 450 |
🎯 having 的核心用法
过滤分组结果
场景:找出总销售额超过 1000 的商品类别
select 商品类别, sum(销售额) 类别总销售额
from sales
group by 商品类别
having sum(销售额)>1000
结果:
商品类别 | 类别总销售额 |
---|---|
水果 | 1550 |
⚠️ 对于聚合函数、group by、having避坑指南
-
select 的字段限制:
-
使用goup by 后,
select
只能包含:-
group by
的字段 -
聚合函数
-
-- 错误示例(商品类别未在group by中) select 日期, 商品类别, sum(销售额) from sales group by 日期 -- 正确示例 select 日期, sum(销售额) from sales group by 日期
-
-
别名使用:
-
having可以直接用
select
中的别名(但部分数据库不支持)
select 日期, sum(销售额) total from sales group by 日期 having total > 900 -- MySQL支持,但Oracle不支持
-
-
多层聚合:
-
不能在 where或 having中嵌套聚合函数
-- 错误示例 having(sum(销售额)) > 1000 -- 想实现得使用下面会讲到的子查询
-
limit
🧩 limit 是什么?
它是 SQL 中的「展示控制器」,帮你限制查询结果返回的行数。
核心功能:
-
只显示需要的数据
-
常用于分页查询或排行榜
🌰 基础数据表
假设商品表 products
如下:
id | 商品名 | 价格 |
---|---|---|
1 | 苹果 | 5 |
2 | 香蕉 | 3 |
3 | 橙子 | 4 |
4 | 土豆 | 2 |
5 | 可乐 | 6 |
🎯limit 的核心用法
1. 限制返回行数
场景:只显示第前 3 件商品
select *
from products
limit 3
结果:
id | 商品名 | 价格 |
---|---|---|
1 | 苹果 | 5 |
2 | 香蕉 | 3 |
3 | 橙子 | 4 |
2. 结合 offset
场景:每页显示 2 件商品,查看第 2 页
select *
from products
limit 2 offset 2 -- 跳过前2条,取接下来的2条
结果:
id | 商品名 | 价格 |
---|---|---|
3 | 橙子 | 4 |
4 | 土豆 | 2 |
⚠️ 注意事项
-
性能优化:
-
对大数据量分页时,
limit
和 offset可能导致性能问题 -
建议结合索引使用,或改用基于游标的分页(如
where id > ?
)
-
-
语法差异:
-
MySQL、PostgreSQL 支持
limit
和 offset -
SQL Server 用 top和 offset
fetch
-
Oracle 用 rownum 或 fetch
first
-
-
offset 的起始值:
-
offset 0
表示从第 1 条开始 -
offset N
表示跳过前 N 条
-
sql运行原理
🧩 SQL 的运行原理
SQL 的执行过程就像在超市购物:
-
选择超市(from) → 决定去哪个超市
-
挑选商品(where) → 根据需求筛选商品
-
分类整理(group by) → 按类别或品牌分组
-
计算总价(聚合函数) → 统计每组的金额
-
筛选结果(having) → 过滤掉不符合条件的分组
-
选择展示(select) → 决定展示哪些信息
-
排序(order by) → 按价格或品牌排序
-
打包带走(limit) → 只拿前几件商品
🎯 SQL 的执行顺序
SQL 的执行顺序不是按书写顺序,而是按以下逻辑顺序:
from → where → group by → 聚合函数 → having → select → order by → limit
🌰 用例子说明
假设有一张 products
表:
id | 商品名 | 价格 | 类别 |
---|---|---|---|
1 | 苹果 | 5 | 水果 |
2 | 香蕉 | 3 | 水果 |
3 | 橙子 | 4 | 水果 |
4 | 土豆 | 2 | 蔬菜 |
5 | 可乐 | 6 | 饮料 |
查询需求:找出价格低于 5 元的水果,按价格升序排列,只显示前 2 条
SQL 语句:
select 商品名, 价格
from products
where类别 = '水果' and 价格 < 5
order by 价格 asc
limit 2
🔧 执行步骤拆解
-
from products → 选择
products
表(进入超市) -
where 类别 = '水果' and 价格 < 5 → 筛选出水果类且价格低于 5 元的商品
-
符合条件的商品:香蕉(3)、橙子(4)
-
-
select 商品名, 价格 → 选择要展示的字段(商品名和价格)
-
order by 价格 asc → 按价格升序排列
-
排序结果:香蕉(3)、橙子(4)
-
-
limit 2 → 只取前 2 条
-
最终结果:香蕉(3)、橙子(4)
-
💡 详细执行顺序
1. from
-
作用:确定数据来源(表或子查询)
-
示例:
from products
→ 从products
表加载数据
2. where
-
作用:过滤行(根据条件筛选数据)
-
示例:
where类别 = '水果' and 价格 < 5
→ 只保留水果类且价格低于 5 元的商品
3. group by
-
作用:分组(按指定字段分组)
-
示例:
group by 类别
→ 按类别分组
4. 聚合函数
-
作用:对每组数据进行汇总计算
-
示例:
sum(价格)
→ 计算每组的销售额
5. having
-
作用:过滤分组结果
-
示例:
having sum(价格) > 10
→ 只保留总销售额超过 10 元的组
6. select
-
作用:选择要展示的字段
-
示例:select
商品名, 价格
→ 只展示商品名和价格
7. order by
-
作用:排序(按指定字段升序或降序)
-
示例:order by
价格 asc
→ 按价格升序排列
8. limit
-
作用:限制返回的行数
-
示例:
limit 2
→ 只返回前 2 条数据
⚠️ 注意事项
-
执行顺序与书写顺序不同:
-
比如
select
写在最前面,但实际执行在where
和group by
之后
-
-
where 和 having 的区别:
-
where
在分组前过滤行 -
having
在分组后过滤组
-
-
性能优化:
-
尽量先用 where 减少数据量,再用
group by
和 hacving -
对大数据量排序时,尽量结合索引使用
-
✅ 总结:
SQL 的运行原理就像超市购物:
-
选择超市(from)
-
挑选商品(where)
-
分类整理(group by)
-
计算总价(聚合函数)
-
筛选结果(having)
-
选择展示(select)
-
排序(order by)
-
打包带走(limit)
sql书写顺序
🧩 SQL 的书写顺序
书写顺序是我们写 SQL 语句时的逻辑顺序,通常如下:
select → from → where → group by → having → order by → limit
🔧 书写顺序 vs 执行顺序
书写顺序 | 执行顺序 | 说明 |
---|---|---|
select | 5. select | 选择展示的字段 |
from | 1. from | 确定数据来源 |
where | 2. where | 过滤行 |
group by | 3. group by | 分组 |
having | 4. having | 过滤分组结果 |
order by | 6. order by | 排序 |
limit | 7. limit | 限制返回的行数 |
💡 为什么书写顺序和执行顺序不同?
SQL 的设计是为了让用户以更直观的方式描述需求,而不是关注底层实现。
-
书写顺序:从用户的角度描述需求(先选字段,再选表,再过滤,再排序)
-
执行顺序:从数据库的角度优化执行(先加载数据,再过滤,再分组,再排序)
⚠️ 注意事项
-
书写顺序是固定的:
-
必须按
select → from → wher→ group by → hacing → order by → limit
的顺序写 -
不能随意调换顺序(比如
where
不能写在 select的前面)
-
-
执行顺序是优化的:
-
数据库会根据执行顺序优化查询性能
-
比如先过滤(
where
)再分组(group by
),可以减少计算量
-
-
别名的作用域:
-
select
中的别名可以在order by 和 having中使用 -
但不能在
where
或group by
中使用
-
if 与 case when
🧩 if 和 case when 是什么?
它们是 SQL 中的「条件判断工具」,用来根据条件返回不同的值。
-
if → 简单的二选一
-
case when → 复杂的多条件判断
🌰 基础数据表
假设有一张 products
表:
id | 商品名 | 价格 | 类别 |
---|---|---|---|
1 | 苹果 | 5 | 水果 |
2 | 香蕉 | 3 | 水果 |
3 | 橙子 | 4 | 水果 |
4 | 土豆 | 2 | 蔬菜 |
5 | 可乐 | 6 | 饮料 |
🎯 if 的用法
1. 基本语法
if(条件, 值1, 值2)
-
如果条件为真,返回值1;否则返回值2
2. 示例
场景:如果价格大于 4 元,标记为「高价」,否则标记为「低价」
select 商品名, 价格, IF(价格 > 4, '高价', '低价') 价格分类
from products
结果:
商品名 | 价格 | 价格分类 |
---|---|---|
苹果 | 5 | 高价 |
香蕉 | 3 | 低价 |
橙子 | 4 | 低价 |
土豆 | 2 | 低价 |
可乐 | 6 | 高价 |
🎯 case when 的用法
1. 基本语法
case
when 条件1 then 值1
when 条件2 then 值2
...
else 默认值
end
2. 示例
场景:根据价格区间分类
-
价格 < 3 → 低价
-
3 ≤ 价格 < 5 → 中价
-
价格 ≥ 5 → 高价
select 商品名, 价格,
case
when 价格 < 3 then '低价'
when 价格 < 5 then '中价'
else '高价'
end 价格分类
from products
结果:
商品名 | 价格 | 价格分类 |
---|---|---|
苹果 | 5 | 高价 |
香蕉 | 3 | 中价 |
橙子 | 4 | 中价 |
土豆 | 2 | 低价 |
可乐 | 6 | 高价 |
💡 if 和 case when 的区别
特性 | if | case when |
---|---|---|
适用场景 | 简单的二选一 | 复杂的多条件判断 |
可读性 | 简单直观 | 更适合多条件逻辑 |
灵活性 | 只能处理一个条件 | 可以处理多个条件 |
性能 | 性能稍好 | 性能稍差(条件多时) |
⚠️ 注意事项
-
if 的局限性:
-
只能处理一个条件,复杂逻辑建议用
case when
-
-
case when 的顺序:
-
条件从上到下匹配,匹配到第一个满足的条件后即返回结果
-
把最严格的条件写在最前面
-
-
else 的默认值:
-
如果没有else,且所有条件都不满足,则返回 null
-
窗口函数
🧩 窗口函数是什么?
它是 SQL 中的「动态分析工具」,可以在不改变原始数据的情况下,对每一行数据进行额外的计算和分析。
核心特点:
-
不聚合数据(不像
group by
会把多行合并成一行) -
可以同时看到原始数据和计算结果
🌰 基础数据表
假设有一张 sales
表记录每日销售数据:
日期 | 商品名 | 销售额 |
---|---|---|
2023-08-01 | 苹果 | 500 |
2023-08-01 | 香蕉 | 300 |
2023-08-02 | 苹果 | 600 |
2023-08-02 | 香蕉 | 400 |
2023-08-03 | 苹果 | 450 |
🎯 窗口函数的基本语法
函数名称()over(
partition by 分组字段
order by 排序字段
rows between 起始行 and 结束行
)
🚀 五大常用窗口函数
1. row_number() → 行号
场景:给每天的商品销售额排名
select
日期, 商品名, 销售额,
row_number over(partition by 日期 order by 销售额 desc) 排名
from sales
结果:
日期 | 商品名 | 销售额 | 排名 |
---|---|---|---|
2023-08-01 | 苹果 | 500 | 1 |
2023-08-01 | 香蕉 | 300 | 2 |
2023-08-02 | 苹果 | 600 | 1 |
2023-08-02 | 香蕉 | 400 | 2 |
2023-08-03 | 苹果 | 450 | 1 |
2. rank() → 排名(允许并列)
场景:如果销售额相同,排名并列
select
日期, 商品名, 销售额,
rank() over(partition by 日期 order by 销售额 desc) 排名
from sales
结果:
日期 | 商品名 | 销售额 | 排名 |
---|---|---|---|
2023-08-01 | 苹果 | 500 | 1 |
2023-08-01 | 香蕉 | 300 | 2 |
2023-08-02 | 苹果 | 600 | 1 |
2023-08-02 | 香蕉 | 400 | 2 |
2023-08-03 | 苹果 | 450 | 1 |
3. dense_rank() → 密集排名(允许并列,但排名连续)
场景:如果销售额相同,排名并列且连续
select
日期,商品名,销售额,
dense_rank() over(partition by 日期 order by 销售额 desc) 排名
from sales
结果:
日期 | 商品名 | 销售额 | 排名 |
---|---|---|---|
2023-08-01 | 苹果 | 500 | 1 |
2023-08-01 | 香蕉 | 300 | 2 |
2023-08-02 | 苹果 | 600 | 1 |
2023-08-02 | 香蕉 | 400 | 2 |
2023-08-03 | 苹果 | 450 | 1 |
4. sum() over() → 累计值
场景:计算每天商品的累计销售额
select
日期,商品名,销售额
sum(销售额) over(partition by 日期 order by 销售额 desc) 累计销售额
from sales
结果:
日期 | 商品名 | 销售额 | 累计销售额 |
---|---|---|---|
2023-08-01 | 苹果 | 500 | 500 |
2023-08-01 | 香蕉 | 300 | 800 |
2023-08-02 | 苹果 | 600 | 600 |
2023-08-02 | 香蕉 | 400 | 1000 |
2023-08-03 | 苹果 | 450 | 450 |
5.lag() / lead() → 前后行数据
基础语法:
lag(字段名,偏移量)over() --lag是向上面行偏移
lead(字段名,偏移量)over() --lead是向下面行偏移
场景:查看前一天的商品销售额
select
日期,商品名,销售额
lag(销售额,1) over(partition by 日期 order by 销售额 desc) 前一天销售额
from sales
结果:
日期 | 商品名 | 销售额 | 前一天销售额 |
---|---|---|---|
2023-08-01 | 苹果 | 500 | NULL |
2023-08-02 | 苹果 | 600 | 500 |
2023-08-03 | 苹果 | 450 | 600 |
2023-08-01 | 香蕉 | 300 | NULL |
2023-08-02 | 香蕉 | 400 | 300 |
⚠️ 注意事项
-
partition by:
-
用于分组,类似于
group by
,但不会合并行
-
-
order by:
-
用于排序,决定窗口函数的计算顺序
-
-
rows between:
-
用于定义窗口范围(如前 2 行到当前行)
-
-
性能问题:
-
窗口函数对大数据量可能较慢,尽量结合索引使用
-
表连接
🧩 表连接是什么?
它是 SQL 中的「数据桥梁」,用来将多张表的数据合并在一起。
核心功能:
-
根据关联字段(如商品ID)将多张表的数据匹配起来
-
常见的连接方式:
inner join、
left join、right join、full join
🌰 基础数据表
假设有两张表:
商品表 products
商品ID | 商品名 | 价格 |
---|---|---|
1 | 苹果 | 5 |
2 | 香蕉 | 3 |
3 | 橙子 | 4 |
订单表 orders
订单ID | 商品ID | 数量 |
---|---|---|
101 | 1 | 2 |
102 | 3 | 1 |
103 | 4 | 5 |
🎯 四大常用表连接
1. inner join→ 内连接
场景:找出有订单的商品信息
select
p.商品名,p.价格,o.数量
from products p
inner join orders o
on p.商品ID=o.商品ID
结果:
商品名 | 价格 | 数量 |
---|---|---|
苹果 | 5 | 2 |
橙子 | 4 | 1 |
解释:
-
只返回两张表中匹配的行
-
订单ID=103 的商品ID=4 在商品表中不存在,因此被过滤掉
2. left join → 左连接
场景:找出所有商品信息,并显示对应的订单信息(如果有)
select
p.商品名,p.价格,o.数量
from products p
left join orders o
on p.商品ID=o.商品ID
结果:
商品名 | 价格 | 数量 |
---|---|---|
苹果 | 5 | 2 |
香蕉 | 3 | NULL |
橙子 | 4 | 1 |
解释:
-
返回左表(products)的所有行,右表(orders)没有匹配的行显示为
null
-
香蕉没有订单,因此数量为
null
3. right join → 右连接
场景:找出所有订单信息,并显示对应的商品信息(如果有)
select
p.商品名,p.价格,o.数量
from products p
right join orders o
on p.商品ID=o.商品ID
结果:
商品名 | 价格 | 数量 |
---|---|---|
苹果 | 5 | 2 |
橙子 | 4 | 1 |
NULL | NULL | 5 |
解释:
-
返回右表(orders)的所有行,左表(products)没有匹配的行显示为
null
-
订单ID=103 的商品ID=4 在商品表中不存在,因此商品名和价格为
null
4. full join → 全外连接
场景:找出所有商品和订单信息,显示所有匹配和不匹配的行
select
p.商品名,p.价格,o.数量
from products p
full join orders o
on p.商品ID=o.商品ID
结果:
商品名 | 价格 | 数量 |
---|---|---|
苹果 | 5 | 2 |
香蕉 | 3 | NULL |
橙子 | 4 | 1 |
NULL | NULL | 5 |
解释:
-
返回两张表的所有行,没有匹配的行显示为 null
-
MySQL 不支持
full join
,可以用 union实现:
select
p.商品名, p.价格, o.数量
from products p
left orders o
on p.商品ID = o.商品ID
union
select
p.商品名, p.价格, o.数量
from products p
right join orders o
on p.商品ID = o.商品ID;
⚠️ 注意事项
-
连接条件:
-
必须指定连接条件(如 on
p.商品ID = o.商品ID
),否则会产生笛卡尔积
-
-
性能问题:
-
对大数据量连接时可能较慢,尽量结合索引使用
-
-
null值处理:
-
左连接或右连接时,未匹配的行会显示为
Null
-
子查询
🧩 子查询是什么?
它是 SQL 中的「查询中的查询」,先解决一个小问题,再用结果去解决更大的问题。
核心功能:
-
嵌套在另一个查询中
-
可以出现在
select
、from
、where
、having
等子句中
🌰 基础数据表
假设有两张表:
商品表 products
商品ID | 商品名 | 价格 |
---|---|---|
1 | 苹果 | 5 |
2 | 香蕉 | 3 |
3 | 橙子 | 4 |
订单表 orders
订单ID | 商品ID | 数量 |
---|---|---|
101 | 1 | 2 |
102 | 3 | 1 |
103 | 4 | 5 |
🎯 子查询的 4 种核心用法
1. 标量子查询 → 返回单个值
场景:找出价格高于平均价格的商品
select *
from products
where 价格 > (
select avg(价格)
from products
)
结果:
商品ID | 商品名 | 价格 |
---|---|---|
1 | 苹果 | 5 |
解释:
-
内层查询:
select avg(价格) from products
→ 得到4
-
外层查询:
where 价格 > 4
→ 苹果(5)
2. 列子查询 → 返回一列值
场景:找出有订单的商品信息
select *
from products
where 商品ID in (
select 商品ID
from orders
)
结果:
商品ID | 商品名 | 价格 |
---|---|---|
1 | 苹果 | 5 |
3 | 橙子 | 4 |
解释:
-
内层查询:
select 商品ID from orders
→ 得到1, 3
-
外层查询:
where 商品ID in (1, 3)
→ 苹果、橙子
3. 行子查询 → 返回一行数据
场景:找出价格和库存与橙子完全相同的商品
select *
from products
where(价格,库存) =(
select 价格,库存
from products
where 商品名 = '橙子'
)
结果:
商品ID | 商品名 | 价格 |
---|---|---|
3 | 橙子 | 4 |
解释:
-
内层查询:
select 价格, 库存 from products where 商品名 = '橙子'
→ 得到(4, 120)
-
外层查询:
where (价格, 库存) = (4, 120)
→ 橙子
4. 表子查询 → 返回多行多列
场景:先筛选出水果类商品,再按价格排序
select *
from(
select *
from products
where 类别 = '水果'
) 水果表
order by 价格 desc
结果:
商品ID | 商品名 | 价格 |
---|---|---|
1 | 苹果 | 5 |
3 | 橙子 | 4 |
2 | 香蕉 | 3 |
⚠️ 注意事项
-
性能问题:
-
子查询可能逐行执行,性能较差
-
尽量用
join
替代复杂子查询
-
-
别名作用域:
-
内层查询的别名在外层不可见
-
-
null值处理:
-
子查询可能返回 null,导致主查询无结果
-
常用函数
🧩 一、日期函数
日期函数用于处理日期和时间数据,比如计算日期差、提取年月日等。
1. 获取当前日期和时间
-
current_date→ 当前日期
select current_date; --比如 2023-08-07
2. 提取日期部分
-
year()
→ 提取年份
select year('2023-08-07'); -- 2023
month()
→ 提取月份
select month('2023-08-07'); -- 8
- day
()
→ 提取日
select day('2023-08-07'); -- 7
3. 格式化日期
-
date_format()
→ 格式化日期
select date_fomat('2023-08-07', '%Y年%m月%d日'); -- 2023年08月07日
🧩 二、字符串函数
字符串函数用于处理文本数据,比如拼接、截取、替换等。
1. 拼接字符串
-
concat()
→ 拼接字符串
select concat('Hello', ' ', 'World'); -- Hello World
2. 截取字符串
-
substring()
→ 截取子串
select substring('Hello World', 1, 5); -- Hello
3. 替换字符串
-
replace()
→ 替换字符串
select replace('Hello World', 'World', 'SQL'); -- Hello SQL
🧩 三、数学函数
数学函数用于处理数值数据,比如四舍五入、取绝对值等。
1. 四舍五入
-
round()
→ 四舍五入
select round(3.14159, 2); -- 3.14
🧩 四、等等
博主总结了以上sql知识,基本上涵盖了数据分析中sql入门的全部知识 ,由于是博主一条条边学边总结边写出来的知识,如若存在错误请多多指正!!也希望能帮到学习相关内容的你!!