商务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 NULLCOALESCE示例:
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
- 从复制常见的多表报表开始
- 记录查询以便团队协作