商务SQL精简
一份按课程模块组织的SQL关键概念快速参考指南。
1. 🔍 SQL基础
1.1 数据库:超级Excel工作簿
关键对比:
Excel术语 | SQL/数据库术语 |
---|---|
工作表/表格 | 表(Table) |
列 | 列/字段(Column/Field) |
行 | 记录(Record) |
工作簿 | 数据库(Database) |
为什么使用数据库?
- 可处理数百万行数据
- 分析速度更快
- 支持多用户访问
- 更好的数据完整性
Excel与SQL任务对比:
Excel操作 | SQL等效操作 |
---|---|
筛选行 | WHERE 子句 |
选择列 | SELECT 语句 |
数据排序 | ORDER BY 子句 |
计算列 | SELECT 中的表达式 |
数据透视表 | GROUP BY 聚合 |
1.2 第一个SELECT语句
基本语法:
sql
SELECT * FROM table_name;
关键点:
SELECT *
检索所有列FROM
指定要查询的表- 相当于在Excel中打开一个工作表
示例:
sql
SELECT * FROM sales;
返回结果:
SaleDate | Product | Amount |
---|---|---|
2024-05-01 | Apples | 120 |
2024-05-01 | Oranges | 80 |
1.3 选择特定列
基本语法:
sql
SELECT column1, column2 FROM table_name;
列别名:
sql
SELECT column1 AS alias1, column2 AS alias2 FROM table_name;
关键点:
- 在SELECT后列出用逗号分隔的列
- 使用AS为结果中的列重命名
- 查询中列的顺序决定输出顺序
示例:
sql
SELECT Product, Amount FROM sales;
返回结果:
Product | Amount |
---|---|
Apples | 120 |
Oranges | 80 |
sql
SELECT Product AS 商品, Amount AS 总金额 FROM sales;
返回结果:
商品 | 总金额 |
---|---|
Apples | 120 |
Oranges | 80 |
2. ⚙️ 数据筛选
2.1 WHERE: SQL筛选器
基本语法:
sql
SELECT columns FROM table_name
WHERE condition;
比较运算符:
运算符 | 含义 | 示例 |
---|---|---|
= | 等于 | Product = 'Apples' |
<> | 不等于 | Product <> 'Oranges' |
> | 大于 | Amount > 100 |
< | 小于 | Amount < 100 |
>= | 大于等于 | Amount >= 100 |
<= | 小于等于 | Amount <= 100 |
NULL处理:
sql
WHERE column IS NULL
WHERE column IS NOT NULL
COALESCE示例:
sql
SELECT *, COALESCE(Amount, 0) AS Amount_Defaulted
FROM sales
WHERE COALESCE(Amount, 0) > 100;
关键点:
- WHERE根据条件筛选行
- 使用IS NULL/IS NOT NULL检查NULL值
- COALESCE为NULL值提供默认值
2.2 数字和范围筛选
范围筛选:
sql
WHERE column BETWEEN value1 AND value2
多值筛选:
sql
WHERE column IN (value1, value2, ...)
组合条件:
sql
WHERE condition1 AND condition2
WHERE condition1 OR condition2
示例:
sql
SELECT * FROM sales
WHERE Amount BETWEEN 80 AND 120;
sql
SELECT * FROM sales
WHERE Product IN ('Apples', 'Oranges');
sql
SELECT * FROM sales
WHERE Product = 'Apples' AND Amount > 100;
关键点:
- BETWEEN包含两个端点值
- IN匹配列表中的任何值
- AND/OR组合多个条件
2.3 使用LIKE进行文本搜索
模式匹配:
sql
WHERE column LIKE '%pattern%'
通配符:
%
匹配任意数量字符_
匹配单个字符
示例:
sql
-- 包含"App"
WHERE Product LIKE '%App%'
-- 以"App"开头
WHERE Product LIKE 'App%'
-- 以"es"结尾
WHERE Product LIKE '%es'
-- 不区分大小写搜索
WHERE LOWER(Product) LIKE '%app%'
关键点:
- LIKE支持灵活的文本模式匹配
- 类似于Excel的"包含"筛选
- 使用LOWER()进行不区分大小写搜索
2.4 多条件筛选
组合条件:
sql
WHERE condition1 AND condition2
WHERE condition1 OR condition2
括号分组:
sql
WHERE (condition1 AND condition2) OR condition3
示例:
sql
-- AND示例
WHERE Product = 'Apples' AND Amount > 100
-- OR示例
WHERE Product = 'Apples' OR Product = 'Oranges'
-- 复杂分组
WHERE (Product = 'Apples' AND Amount > 100) OR Product = 'Oranges'
常见错误:
- 使用= NULL而不是IS NULL
- 复杂条件中忘记使用括号
- 文本值周围忘记加引号
- 忽略大小写敏感性
关键点:
- 使用AND/OR组合条件
- 括号控制求值顺序
- 始终使用IS NULL检查NULL值
- 为文本值加引号并考虑大小写敏感性
3. 🔄 数据转换
3.1 使用ORDER BY排序
基本语法:
sql
SELECT columns FROM table_name
ORDER BY column1 [ASC|DESC];
排序方向:
ASC
- 升序(A-Z, 0-9) - 默认DESC
- 降序(Z-A, 9-0)
示例:
sql
-- 单列排序
SELECT * FROM sales
ORDER BY Amount DESC;
-- 多列排序
SELECT * FROM sales
ORDER BY Product ASC, Amount DESC;
关键点:
- ORDER BY对最终结果集排序
- 可以按多列顺序排序
- 类似于Excel的排序功能
3.2 使用LIMIT分页结果
基本语法:
sql
SELECT columns FROM table_name
LIMIT number_of_rows;
常见用途:
- 预览数据而不加载完整结果
- 提高查询性能
- 导出数据样本
- 防止大型结果集过载
示例:
sql
-- 获取前100行
SELECT * FROM sales LIMIT 100;
-- 获取金额最高的10条记录
SELECT * FROM sales
ORDER BY Amount DESC
LIMIT 10;
关键点:
- LIMIT控制返回的行数
- 常与ORDER BY一起使用以获得有意义的结果
- 许多工具出于安全考虑会应用默认LIMIT
3.3 列计算
基本语法:
sql
SELECT column1, column2, expression AS alias FROM table_name;
常见操作:
- 算术运算:
+
,-
,*
,/
- 函数:
ROUND()
,UPPER()
,LOWER()
- 连接:
||
或CONCAT()
示例:
sql
-- 简单计算
SELECT Product, Amount, Amount * 1.2 AS Amount_With_Tax FROM sales;
-- 使用函数
SELECT Product, UPPER(Product) AS Product_Upper FROM sales;
-- 数字四舍五入
SELECT Product, ROUND(Amount, 0) AS Rounded_Amount FROM sales;
关键点:
- 计算在SELECT子句中完成
- 使用AS命名计算列
- 支持大多数类似Excel的操作和函数
3.4 文本处理
基本语法:
sql
SELECT text_function(column) FROM table_name;
常见文本函数:
- 连接:
||
或CONCAT()
- 子字符串:
LEFT()
,RIGHT()
,SUBSTRING()
- 大小写转换:
UPPER()
,LOWER()
- 长度:
LENGTH()
或LEN()
示例:
sql
-- 连接
SELECT Product || ' - $' || Amount AS Product_Price FROM sales;
-- 子字符串
SELECT LEFT(Product, 3) AS First3, SUBSTRING(Product, 2, 3) AS Mid3 FROM sales;
-- 大小写转换
SELECT UPPER(Product) AS UpperCase, LOWER(Product) AS LowerCase FROM sales;
-- 文本长度
SELECT Product, LENGTH(Product) AS Name_Length FROM sales;
关键点:
- 功能类似于Excel文本函数
- 语法可能因数据库系统略有不同
- 对格式化和清理文本数据很有用
3.5 使用CASE进行智能分类
基本语法:
sql
SELECT column,
CASE
WHEN condition1 THEN result1
WHEN condition2 THEN result2
ELSE default_result
END AS new_column
FROM table_name;
常见用途:
- 从数值范围创建分类
- 将值映射到标签
- 使用默认值处理NULL值
- 实现条件逻辑
示例:
sql
-- 简单分类
SELECT Product, Amount,
CASE
WHEN Amount >= 100 THEN '高'
WHEN Amount >= 50 THEN '中'
ELSE '低'
END AS Amount_Category
FROM sales;
-- 值映射
SELECT Product,
CASE
WHEN Product = 'Apples' THEN '水果'
WHEN Product = 'Carrots' THEN '蔬菜'
ELSE '其他'
END AS Product_Type
FROM sales;
-- NULL处理
SELECT Product,
CASE
WHEN Amount IS NULL THEN 0
ELSE Amount
END AS Amount_Filled
FROM sales;
关键点:
- 类似于Excel的IF/IFS函数
- 按顺序评估条件
- 需要使用END关闭CASE语句
- 使用AS命名结果列
4. 📊 数据聚合
4.1 基本聚合函数
基本语法:
sql
SELECT aggregate_function(column) FROM table_name;
常见函数:
函数 | 功能 | 示例 |
---|---|---|
SUM() | 求和 | SUM(Amount) |
AVG() | 计算平均值 | AVG(Amount) |
COUNT() | 计数行数 | COUNT(*) |
MIN() | 查找最小值 | MIN(Amount) |
MAX() | 查找最大值 | MAX(Amount) |
示例:
sql
-- 销售总额
SELECT SUM(Amount) AS Total_Sales FROM sales;
-- 多个聚合
SELECT
COUNT(*) AS Row_Count,
SUM(Amount) AS Total_Sales,
AVG(Amount) AS Avg_Sale,
MIN(Amount) AS Min_Sale,
MAX(Amount) AS Max_Sale
FROM sales;
关键点:
- 类似于Excel的汇总函数和数据透视表值
- 可以在同一查询中使用多个函数
- 计算时忽略NULL值
4.2 GROUP BY: 改变游戏规则
基本语法:
sql
SELECT column, aggregate_function(column)
FROM table_name
GROUP BY column;
示例:
sql
-- 按产品统计销售总额
SELECT Product, SUM(Amount) AS Total_Sales
FROM sales
GROUP BY Product;
-- 按日期统计销售总额
SELECT SaleDate, SUM(Amount) AS Total_Sales
FROM sales
GROUP BY SaleDate
ORDER BY SaleDate;
关键规则:
- SELECT中每个非聚合列必须在GROUP BY中
- 类似于Excel数据透视表的行标签
- 可以按多列分组(逗号分隔)
关键点:
- GROUP BY允许按类别汇总数据
- 对创建有意义的报告至关重要
- 常与ORDER BY一起使用以获得排序结果
4.3 多级分组
基本语法:
sql
SELECT column1, column2, aggregate_function(column)
FROM table_name
GROUP BY column1, column2;
示例:
sql
-- 按产品和日期统计销售总额
SELECT Product, SaleDate, SUM(Amount) AS Total_Sales
FROM sales
GROUP BY Product, SaleDate
ORDER BY Product, SaleDate;
关键点:
- 类似于Excel数据透视表中的嵌套行标签
- GROUP BY中列的顺序影响分组
- 每个分组列组合获得自己的行
4.4 使用HAVING筛选分组
基本语法:
sql
SELECT column, aggregate_function(column)
FROM table_name
GROUP BY column
HAVING condition;
示例:
sql
-- 总销售额超过200的产品
SELECT Product, SUM(Amount) AS Total_Sales
FROM sales
GROUP BY Product
HAVING SUM(Amount) > 200;
-- 组合WHERE和HAVING
SELECT Product, SUM(Amount) AS Total_Sales
FROM sales
WHERE SaleDate BETWEEN '2024-05-01' AND '2024-05-31'
GROUP BY Product
HAVING Total_Sales > 200;
关键点:
- HAVING在聚合后筛选分组(WHERE在聚合前筛选行)
- 可以引用聚合函数或列别名
- 类似于在Excel中筛选数据透视表结果
5. 📅 高级技巧
5.1 日期处理
基本日期筛选:
sql
SELECT * FROM sales
WHERE SaleDate BETWEEN '2024-05-01' AND '2024-05-31';
日期提取函数:
sql
SELECT
SaleDate,
YEAR(SaleDate) AS Sale_Year,
MONTH(SaleDate) AS Sale_Month,
DAY(SaleDate) AS Sale_Day
FROM sales;
按日期部分分组:
sql
SELECT
YEAR(SaleDate) AS Year,
MONTH(SaleDate) AS Month,
SUM(Amount) AS Total_Sales
FROM sales
GROUP BY YEAR(SaleDate), MONTH(SaleDate)
ORDER BY Year, Month;
日期运算:
sql
-- 添加天数
SELECT SaleDate, SaleDate + 7 AS Week_Later FROM sales;
-- 日期差异(天数)
SELECT EndDate - StartDate AS Days_Diff FROM sales;
常见数据库差异:
函数 | PostgreSQL/Oracle | SQL Server | MySQL | Snowflake |
---|---|---|---|---|
提取年份 | YEAR(date) | YEAR(date) | YEAR(date) | YEAR(date) |
格式化日期 | TO_CHAR(date, 'YYYY-MM') | FORMAT(date, 'yyyy-MM') | DATE_FORMAT(date, '%Y-%m') | TO_VARCHAR(date, 'YYYY-MM') |
添加天数 | date + n | DATEADD(day, n, date) | DATE_ADD(date, INTERVAL n DAY) | DATEADD(day, n, date) |
关键点:
- 日期函数因数据库而异 - 请查阅文档
- 功能类似于Excel日期函数
- 对基于时间的分析和报告至关重要
5.2 NULL值解决方案
理解NULL:
- 表示缺失/未知数据(类似于Excel空白)
- 不等于零或空字符串
筛选NULL值:
sql
-- 查找NULL值
SELECT * FROM sales WHERE Amount IS NULL;
-- 排除NULL值
SELECT * FROM sales WHERE Amount IS NOT NULL;
替换NULL值:
sql
-- COALESCE提供默认值
SELECT Product, COALESCE(Amount, 0) AS Amount_Filled FROM sales;
-- CASE语句替代方案
SELECT Product,
CASE
WHEN Amount IS NULL THEN '缺失'
ELSE CAST(Amount AS VARCHAR)
END AS Amount_Status
FROM sales;
关键点:
- 始终使用IS NULL/IS NOT NULL检查NULL值
- COALESCE是处理NULL值的标准方法
- CASE提供更灵活的NULL处理
5.3 子查询基础
什么是子查询?
- 嵌套在其他查询中的查询
- 类似于Excel中的辅助表/公式
- 可用于WHERE、IN、EXISTS、SELECT子句
基本子查询语法:
sql
-- 使用子查询结果筛选
SELECT * FROM sales
WHERE Amount > (SELECT AVG(Amount) FROM sales);
-- 使用子查询的IN
SELECT * FROM sales
WHERE Product IN (SELECT Product FROM featured_products);
-- 使用子查询的NOT IN
SELECT * FROM sales
WHERE Product NOT IN (SELECT Product FROM discontinued_products);
NOT IN的NULL处理:
sql
-- 安全的NOT IN(过滤NULL)
SELECT * FROM sales
WHERE Product NOT IN (
SELECT Product FROM discontinued_products
WHERE Product IS NOT NULL
);
-- 使用COALESCE的替代方案
SELECT * FROM sales
WHERE Product NOT IN (
SELECT COALESCE(Product, '???') FROM discontinued_products
);
关键点:
- 子查询支持动态筛选
- 带有NULL的NOT IN可能导致意外结果
- 在使用NOT IN的子查询中始终处理NULL值
6. 🤝 表连接
6.1 INNER JOIN基础
Excel类比: 类似于工作表之间的VLOOKUP
基本语法:
sql
SELECT t1.column1, t2.column2
FROM table1 t1
INNER JOIN table2 t2
ON t1.common_column = t2.common_column;
示例:
sql
-- 合并销售和产品详情
SELECT s.ProductID, p.ProductName, s.Amount
FROM sales s
INNER JOIN products p
ON s.ProductID = p.ProductID;
表别名最佳实践:
- 使用简短、有意义的别名(如s表示sales,p表示products)
- 在整个查询中保持别名一致
- 帮助区分同名列
关键点:
- INNER JOIN只返回两个表中匹配的行
- 连接条件(ON子句)是必需的
- 可以连接任何匹配列,不限于ID
6.2 LEFT JOIN实践
Excel类比: 类似保留#N/A错误的VLOOKUP
基本语法:
sql
SELECT t1.column1, t2.column2
FROM table1 t1
LEFT JOIN table2 t2
ON t1.common_column = t2.common_column;
示例: 包含所有销售,即使没有产品信息
sql
SELECT s.ProductID, p.ProductName, s.Amount
FROM sales s
LEFT JOIN products p
ON s.ProductID = p.ProductID;
查找不匹配项:
sql
-- 没有销售的产品
SELECT p.ProductID, p.ProductName
FROM products p
LEFT JOIN sales s ON p.ProductID = s.ProductID
WHERE s.ProductID IS NULL;
-- 没有产品信息的销售
SELECT s.ProductID, s.Amount
FROM sales s
LEFT JOIN products p ON s.ProductID = p.ProductID
WHERE p.ProductID IS NULL;
关键点:
- LEFT JOIN保留左表所有行
- 不匹配项显示为NULL值
- 使用WHERE IS NULL查找不匹配行
6.3 多表连接
Excel类比: 类似跨工作表的多个VLOOKUP链
基本语法:
sql
SELECT t1.col, t2.col, t3.col
FROM table1 t1
JOIN table2 t2 ON t1.key = t2.key
JOIN table3 t3 ON t1.key = t3.key;
示例: 连接销售、产品和客户表
sql
SELECT s.SaleID, s.Amount, p.ProductName, c.CustomerName
FROM sales s
INNER JOIN products p ON s.ProductID = p.ProductID
INNER JOIN customers c ON s.CustomerID = c.CustomerID;
最佳实践:
- 使用清晰、一致的表别名(s,p,c)
- 按逻辑顺序连接表(从主表开始)
- 增量测试连接(一次添加一个连接)
关键点:
- 可以根据需要连接任意多表
- 每个连接都需要ON条件
- 别名对可读性至关重要
6.4 处理连接重复项
常见原因:
- 连接列中存在重复值
- 多对多关系
- 数据质量问题
诊断重复项:
sql
-- 检查重复键
SELECT join_column, COUNT(*)
FROM table
GROUP BY join_column
HAVING COUNT(*) > 1;
问题示例:
sql
-- 如果products有重复项可能产生重复行
SELECT s.SaleID, p.ProductName, s.Amount
FROM sales s
JOIN products p ON s.ProductID = p.ProductID;
解决方案:
- 从源头修复数据质量(删除重复项)
- 使用DISTINCT(临时解决方案):
sql
SELECT DISTINCT s.SaleID, p.ProductName, s.Amount
FROM sales s
JOIN products p ON s.ProductID = p.ProductID;
- 确保连接列是唯一键
关键点:
- 存在重复项时连接会成倍增加行数
- 连接前始终检查重复项
- 优先修复数据而非使用DISTINCT
6.5 将多表Excel迁移到SQL
Excel到SQL等效操作:
Excel操作 | SQL等效操作 |
---|---|
跨表VLOOKUP | JOIN |
合并多表 | 多个JOIN |
删除重复项 | SELECT DISTINCT |
连接后筛选 | WHERE 在JOIN 后 |
迁移示例:
sql
-- Excel: 使用VLOOKUP合并销售、产品、客户表
-- SQL等效:
SELECT s.SaleID, s.Amount, p.ProductName, c.CustomerName
FROM sales s
JOIN products p ON s.ProductID = p.ProductID
JOIN customers c ON s.CustomerID = c.CustomerID;
迁移优势:
- 更可靠地处理复杂关系
- 自动化重复的多表分析
- 为团队提供单一数据源
关键点:
- SQL连接取代易错的VLOOKUP
- 从复制常见的多表报表开始
- 记录查询以便团队协作