这篇SQL课堂笔记总结了多种数据查询和处理的核心技术。
主要内容包括:
1)条件判断的CASE WHEN和DECODE语法及应用场景;
2)集合运算(UNION、INTERSECT等)的使用要点;
3)EXISTS子查询的高效实现方式;
4)行列转换的多种实现方法(CASE WHEN、DECODE、PIVOT)。
笔记通过具体示例演示了薪资分段、部门统计、成绩表转换等典型场景,并对比了不同技术的适用情况,如EXISTS与IN的效率差异。
最后还提供了员工分类统计等练习题,帮助巩固知识点。
以下是根据你提供的课堂内容整理的结构化复习笔记 ,涵盖了 CASE WHEN、DECODE、集合运算、EXISTS、行列转换等核心知识点,便于学生快速回顾与理解。
📚 SQL 课堂笔记
一、场景判断:CASE WHEN ... END
语法结构
sql
CASE
WHEN 条件1 THEN 返回值1
WHEN 条件2 THEN 返回值2
...
ELSE 默认值
END
-
如果没有
ELSE,默认返回NULL -
整个
CASE WHEN ... END可视为一个字段
示例1:岗位汉化
sql
SELECT
ENAME,
JOB,
CASE WHEN JOB = 'SALESMAN' THEN '销售'
WHEN JOB = 'MANAGER' THEN '经理'
WHEN JOB = 'CLERK' THEN '文员'
ELSE '职员'
END AS NEW_JOB
FROM EMP;
示例2:按部门薪资分三段
sql
SELECT
K.*,
CASE WHEN NT = 1 THEN 'high_sal'
WHEN NT = 2 THEN 'mid_sal'
ELSE 'low_sal'
END AS 薪资标签
FROM (
SELECT
E.*,
NTILE(3) OVER (PARTITION BY DEPTNO ORDER BY SAL DESC) AS NT
FROM EMP E
) K;
示例3:部门人数标签
sql
SELECT
DEPTNO,
CNT,
CASE WHEN CNT > 5 THEN '很多人'
WHEN CNT > 3 AND CNT <= 5 THEN '人不多'
END AS 人数标签
FROM (
SELECT DEPTNO, COUNT(1) AS CNT
FROM EMP
GROUP BY DEPTNO
);
示例4:条件薪资调整
sql
SELECT
DEPTNO,
SUM(CASE WHEN DEPTNO = 10 THEN SAL + 1000
WHEN DEPTNO = 20 THEN SAL + 500
ELSE SAL
END) AS NEW_TOTAL_SAL
FROM EMP
GROUP BY DEPTNO;
二、等值判断:DECODE
语法
sql
DECODE(判断字段, 值1, 返回值1, 值2, 返回值2, ..., 默认值)
- 只支持单字段等值判断
示例:岗位汉化
sql
SELECT
ENAME,
JOB,
DECODE(JOB, 'SALESMAN', '销售',
'MANAGER', '经理',
'CLERK', '文员',
'职员') AS NEW_JOB
FROM EMP;
三、集合运算
| 运算符 | 含义 |
|---|---|
UNION ALL |
合并,不去重 |
UNION |
合并,去重(效率较低) |
INTERSECT |
交集 |
MINUS |
差集(前一个结果集减去后一个) |
示例
sql
SELECT ID FROM TABLEA
UNION ALL
SELECT ID FROM TABLEB;
SELECT ID FROM TABLEA
MINUS
SELECT ID FROM TABLEB;
⚠️ 注意点
-
上下两个
SELECT的字段个数、顺序、类型必须一致 -
排序(
ORDER BY)只能放在最后一个查询之后 -
最终列名以第一个
SELECT为准
四、EXISTS 半连接
语法
sql
SELECT ...
FROM 表A
WHERE EXISTS (SELECT 1 FROM 表B WHERE 关联条件);
-
只要子查询有返回行,
EXISTS就为TRUE -
不关心子查询具体返回什么,通常写
SELECT 1
示例:存在员工的部门
sql
SELECT D.DEPTNO
FROM DEPT D
WHERE EXISTS (
SELECT 1 FROM EMP E WHERE E.DEPTNO = D.DEPTNO
);
示例:不存在员工的部门
sql
SELECT D.DEPTNO
FROM DEPT D
WHERE NOT EXISTS (
SELECT 1 FROM EMP E WHERE E.DEPTNO = D.DEPTNO
);
EXISTS vs IN
| 对比项 | EXISTS | IN |
|---|---|---|
| 实现方式 | 半连接 | 嵌套遍历 |
| 子表大时 | 效率更高 | 效率低 |
| 固定值列表 | 不支持 | 支持(如 IN (10,20)) |
五、行列转换
1. 行转列(多行 → 多列)
方法一:CASE WHEN
sql
SELECT
SNAME,
SUM(CASE WHEN CLASS = '语文' THEN SCORE END) AS 语文,
SUM(CASE WHEN CLASS = '数学' THEN SCORE END) AS 数学,
SUM(CASE WHEN CLASS = '英语' THEN SCORE END) AS 英语
FROM T_SCORE
GROUP BY SNAME;
方法二:DECODE
sql
SELECT
SNAME,
MAX(DECODE(CLASS, '语文', SCORE)) AS 语文,
MAX(DECODE(CLASS, '数学', SCORE)) AS 数学,
MAX(DECODE(CLASS, '英语', SCORE)) AS 英语
FROM T_SCORE
GROUP BY SNAME;
方法三:PIVOT(Oracle)
sql
SELECT * FROM T_SCORE
PIVOT (SUM(SCORE) FOR CLASS IN ('语文' AS 语文, '数学' AS 数学, '英语' AS 英语));
2. 列转行(多列 → 多行)
- 使用
UNPIVOT或UNION ALL
六、课堂练习示例
练习1:员工标签(前/后50%入职)
sql
SELECT
DEPTNO, ENAME, SAL,
CASE WHEN NT = 1 THEN '老员工' ELSE '新员工' END AS 员工标签
FROM (
SELECT
DEPTNO, ENAME, SAL, HIREDATE,
NTILE(2) OVER (PARTITION BY DEPTNO ORDER BY HIREDATE) AS NT
FROM EMP
);
练习2:按员工标签统计平均薪资
sql
SELECT
CASE WHEN NT = 1 THEN '老员工' ELSE '新员工' END AS 员工标签,
AVG(SAL) AS 平均薪资
FROM (
SELECT SAL, NTILE(2) OVER (PARTITION BY DEPTNO ORDER BY HIREDATE) AS NT
FROM EMP
)
GROUP BY CASE WHEN NT = 1 THEN '老员工' ELSE '新员工' END;
✅ 总结重点
-
CASE WHEN适用于复杂条件判断 -
DECODE适用于等值单字段判断 -
集合运算注意字段一致性
-
EXISTS适合子表大的存在性判断 -
行列转换常用
CASE WHEN/DECODE/PIVOT