横扫SQL面试
📌行列转换问题
📊 “面试官让我把一列数据拆成三行,我慌了…”hhhh 别慌!学完这个专题 宝子们绝对没问题!!🤣量大管饱!!!
话不多说——直接上题:🎈🎈🎈🎈🎈🎈🎈
列转行🌟🌟🌟🌟🌟
题目🎯
学生成绩表 student_scores
,结构如下:
student_id | math_score | english_score | science_score |
---|---|---|---|
1 | 85 | 90 | 78 |
2 | 92 | 88 | 95 |
3 | 76 | 70 | 80 |
要求将该表转换为如下格式:
student_id | subject | score |
---|---|---|
1 | math | 85 |
1 | english | 90 |
1 | science | 78 |
2 | math | 92 |
2 | english | 88 |
2 | science | 95 |
3 | math | 76 |
3 | english | 70 |
3 | science | 80 |
📝分步解析
原始表结构 → 列转行操作
┌──────────────┬───────────────┬────────────────┐
│ math_score │ english_score │ science_score │
├──────────────┼───────────────┼────────────────┤
│ 85 │ 90 │ 78 │
└──────────────┴───────────────┴────────────────┘
⇩ UNPIVOT
┌──────────────┬───────────────┬───────┐
│ subject │ score │ ... │
├──────────────┼───────────────┼───────┤
│ math │ 85 │ ... │
│ english │ 90 │ ... │
│ science │ 78 │ ... │
└──────────────┴───────────────┴───────┘
步骤1:提取数学成绩
SELECT student_id, 'math' AS subject, math_score AS score
FROM student_scores
中间表 math_scores
✅
student_id | subject | score |
---|---|---|
1 | math | 85 |
2 | math | 92 |
3 | math | 76 |
步骤2:提取英语成绩
SELECT student_id, 'english' AS subject, english_score AS score
FROM student_scores
中间表 english_scores
✅
student_id | subject | score |
---|---|---|
1 | english | 90 |
2 | english | 88 |
3 | english | 70 |
步骤3:提取科学成绩
SELECT student_id, 'science' AS subject, science_score AS score
FROM student_scores
中间表 science_scores
✅
student_id | subject | score |
---|---|---|
1 | science | 78 |
2 | science | 95 |
3 | science | 80 |
步骤4:合并所有结果✅
-- 合并三个中间表
SELECT ... FROM math_scores
UNION ALL
SELECT ... FROM english_scores
UNION ALL
SELECT ... FROM science_scores
最终结果表 ✅
student_id | subject | score |
---|---|---|
1 | math | 85 |
1 | english | 90 |
1 | science | 78 |
2 | math | 92 |
2 | english | 88 |
2 | science | 95 |
3 | math | 76 |
3 | english | 70 |
3 | science | 80 |
💡 技术要点总结
-
UNION ALL 作用:
- 合并多个查询结果(不去重)
- 比
UNION
更高效(无去重开销)
-
字面量生成分类标签:
'math' AS subject
硬编码科目名称
题目🎯
现有一个水果销售记录表 fruit_sales
,表格结构如下:
store_id | apple_sales | banana_sales | orange_sales |
---|---|---|---|
1 | 100 | 150 | 120 |
2 | 80 | 90 | 110 |
3 | 130 | 105 | 95 |
编写SQL查询,将其转换为以下格式:
store_id | fruit | sales |
---|---|---|
1 | apple | 100 |
1 | banana | 150 |
1 | orange | 120 |
2 | apple | 80 |
2 | banana | 90 |
2 | orange | 110 |
3 | apple | 130 |
3 | banana | 105 |
3 | orange | 95 |
步骤1:提取苹果销售额
SELECT
store_id,
'apple' AS fruit, -- 固定值标记水果类型
apple_sales AS sales -- 提取苹果销售额
FROM fruit_sales
中间表 apple_data
store_id | fruit | sales |
---|---|---|
1 | apple | 100 |
2 | apple | 80 |
3 | apple | 130 |
步骤2:提取香蕉销售额
SELECT
store_id,
'banana' AS fruit,
banana_sales AS sales
FROM fruit_sales
中间表 banana_data
store_id | fruit | sales |
---|---|---|
1 | banana | 150 |
2 | banana | 90 |
3 | banana | 105 |
步骤3:提取橙子销售额
SELECT
store_id,
'orange' AS fruit,
orange_sales AS sales
FROM fruit_sales
中间表 orange_data
store_id | fruit | sales |
---|---|---|
1 | orange | 120 |
2 | orange | 110 |
3 | orange | 95 |
步骤4:合并所有结果
-- 最终查询
SELECT * FROM apple_data
UNION ALL
SELECT * FROM banana_data
UNION ALL
SELECT * FROM orange_data
最终结果表
store_id | fruit | sales |
---|---|---|
1 | apple | 100 |
1 | banana | 150 |
1 | orange | 120 |
2 | apple | 80 |
2 | banana | 90 |
2 | orange | 110 |
3 | apple | 130 |
3 | banana | 105 |
3 | orange | 95 |
完整SQL代码(一步到位) 套路是不是一样~😁
SELECT store_id, 'apple' AS fruit, apple_sales AS sales FROM fruit_sales
UNION ALL
SELECT store_id, 'banana' AS fruit, banana_sales FROM fruit_sales
UNION ALL
SELECT store_id, 'orange' AS fruit, orange_sales FROM fruit_sales
ORDER BY store_id, fruit; -- 可选排序
💡 技术要点总结
操作 | 作用 |
---|---|
UNION ALL | 合并多个查询结果(不去重) |
固定值标记 | 通过硬编码生成分类列(如’apple’) |
别名映射 | 将原始列名映射为新列名(如sales) |
题目🎯
假设有一个员工信息表 employee_info
,结构如下:
employee_id | salary_2023 | salary_2024 | salary_2025 |
---|---|---|---|
1 | 50000 | 55000 | 60000 |
2 | 45000 | 48000 | 52000 |
3 | 60000 | 63000 | 65000 |
要求将该表转换为:
employee_id | year | salary |
---|---|---|
1 | 2023 | 50000 |
1 | 2024 | 55000 |
1 | 2025 | 60000 |
2 | 2023 | 45000 |
2 | 2024 | 48000 |
2 | 2025 | 52000 |
3 | 2023 | 60000 |
3 | 2024 | 63000 |
3 | 2025 | 65000 |
同理~😂😂😂 量大管饱
SELECT employee_id, 2023 AS year, salary_2023 AS salary
FROM employee_info
UNION ALL
SELECT employee_id, 2024 AS year, salary_2024 AS salary
FROM employee_info
UNION ALL
SELECT employee_id, 2025 AS year, salary_2025 AS salary
FROM employee_info;
题目🎯:商品库存统计转换
现有一张商品库存信息表 product_stock
,记录了不同仓库中各类商品的库存数量,表结构如下:
warehouse_id | product_a | product_b | product_c |
---|---|---|---|
1 | 100 | 150 | 80 |
2 | 70 | 90 | 120 |
3 | 130 | 110 | 100 |
要求通过SQL查询,将其转换为如下格式:
warehouse_id | product_name | stock_quantity |
---|---|---|
1 | product_a | 100 |
1 | product_b | 150 |
1 | product_c | 80 |
2 | product_a | 70 |
2 | product_b | 90 |
2 | product_c | 120 |
3 | product_a | 130 |
3 | product_b | 110 |
3 | product_c | 100 |
同理~😂😂😂 量大管饱
SELECT warehouse_id, 'product_a' AS product_name, product_a AS stock_quantity
FROM product_stock
UNION ALL
SELECT warehouse_id, 'product_b' AS product_name, product_b AS stock_quantity
FROM product_stock
UNION ALL
SELECT warehouse_id, 'product_c' AS product_name, product_c AS stock_quantity
FROM product_stock;
题目🎯:季度销售数据转换
假设有一张公司季度销售数据表 quarterly_sales
,记录了不同区域在各个季度的销售额,表结构如下:
region | q1_sales | q2_sales | q3_sales | q4_sales |
---|---|---|---|---|
North | 50000 | 60000 | 55000 | 70000 |
South | 40000 | 45000 | 48000 | 52000 |
East | 60000 | 65000 | 70000 | 75000 |
West | 35000 | 38000 | 42000 | 45000 |
请编写SQL查询,将其转换为:
region | quarter | sales_amount |
---|---|---|
North | q1 | 50000 |
North | q2 | 60000 |
North | q3 | 55000 |
North | q4 | 70000 |
South | q1 | 40000 |
South | q2 | 45000 |
South | q3 | 48000 |
South | q4 | 52000 |
East | q1 | 60000 |
East | q2 | 65000 |
East | q3 | 70000 |
East | q4 | 75000 |
West | q1 | 35000 |
West | q2 | 38000 |
West | q3 | 42000 |
West | q4 | 45000 |
同理~😂😂😂 量大管饱
SELECT region, 'q1' AS quarter, q1_sales AS sales_amount
FROM quarterly_sales
UNION ALL
SELECT region, 'q2' AS quarter, q2_sales AS sales_amount
FROM quarterly_sales
UNION ALL
SELECT region, 'q3' AS quarter, q3_sales AS sales_amount
FROM quarterly_sales
UNION ALL
SELECT region, 'q4' AS quarter, q4_sales AS sales_amount
FROM quarterly_sales;
题目🎯:学生课程成绩转换
有一张学生课程成绩表 student_course_scores
,记录了不同学生在多门课程的成绩,表结构如下:
student_id | math_score | history_score | science_score | art_score |
---|---|---|---|---|
1 | 88 | 92 | 78 | 85 |
2 | 95 | 87 | 90 | 79 |
3 | 76 | 80 | 85 | 82 |
要求把该表转换为:
student_id | course_name | score |
---|---|---|
1 | math | 88 |
1 | history | 92 |
1 | science | 78 |
1 | art | 85 |
2 | math | 95 |
2 | history | 87 |
2 | science | 90 |
2 | art | 79 |
3 | math | 76 |
3 | history | 80 |
3 | science | 85 |
3 | art | 82 |
同理~😂😂😂 量大管饱
SELECT student_id,'math' AS course_name, math_score AS score
FROM student_course_scores
UNION ALL
SELECT student_id, 'history' AS course_name, history_score AS score
FROM student_course_scores
UNION ALL
SELECT student_id,'science' AS course_name, science_score AS score
FROM student_course_scores
UNION ALL
SELECT student_id, 'art' AS course_name, art_score AS score
FROM student_course_scores;
带聚合的行列转换🌟🌟🌟
假设有一张订单详情表 order_details
,记录了不同订单中各类商品的购买数量和价格,表结构如下:
order_id | product_type | quantity | price |
---|---|---|---|
101 | electronics | 2 | 500 |
101 | clothing | 3 | 200 |
102 | electronics | 1 | 800 |
102 | books | 4 | 50 |
103 | clothing | 2 | 300 |
103 | books | 3 | 80 |
现在需要统计每个订单中不同商品类型的总购买金额,并将结果进行行列转换,输出格式如下:
order_id | electronics_amount | clothing_amount | books_amount |
---|---|---|---|
101 | 1000 | 600 | 0 |
102 | 800 | 0 | 200 |
103 | 0 | 600 | 240 |
SELECT
order_id,
SUM(CASE WHEN product_type = 'electronics' THEN quantity * price ELSE 0 END) AS electronics_amount,
SUM(CASE WHEN product_type = 'clothing' THEN quantity * price ELSE 0 END) AS clothing_amount,
SUM(CASE WHEN product_type = 'books' THEN quantity * price ELSE 0 END) AS books_amount
FROM
order_details
GROUP BY
order_id;
行转列🌟🌟🌟🌟🌟
- group by + 聚合函数 + case when(或者if)
题目🎯:不同部门不同职位的员工薪资总和统计与转换
有一张员工信息表 employee_info
,结构如下:
employee_id | department | position | salary |
---|---|---|---|
1 | Sales | Manager | 8000 |
2 | Sales | Clerk | 3000 |
3 | HR | Manager | 7500 |
4 | HR | Clerk | 2800 |
5 | IT | Engineer | 6000 |
6 | IT | Technician | 4500 |
要求先统计每个部门中不同职位的员工薪资总和,再将结果进行行列转换,输出格式如下:
department | Manager_salary | Clerk_salary | Engineer_salary | Technician_salary |
---|---|---|---|---|
Sales | 8000 | 3000 | 0 | 0 |
HR | 7500 | 2800 | 0 | 0 |
IT | 0 | 0 | 6000 | 4500 |
SELECT
department,
SUM(CASE WHEN position = 'Manager' THEN salary ELSE 0 END) AS Manager_salary,
SUM(CASE WHEN position = 'Clerk' THEN salary ELSE 0 END) AS Clerk_salary,
SUM(CASE WHEN position = 'Engineer' THEN salary ELSE 0 END) AS Engineer_salary,
SUM(CASE WHEN position = 'Technician' THEN salary ELSE 0 END) AS Technician_salary
FROM
employee_info
GROUP BY
department;
题目🎯:不同城市不同季节的商品销售数量统计与转换
有一张商品销售表 product_sales
,结构如下:
city | season | product_type | sales_quantity |
---|---|---|---|
Beijing | Spring | Electronics | 100 |
Beijing | Summer | Clothing | 150 |
Shanghai | Spring | Electronics | 80 |
Shanghai | Autumn | Books | 60 |
Guangzhou | Summer | Clothing | 200 |
Guangzhou | Winter | Electronics | 90 |
要求先统计每个城市在不同季节的各类商品销售数量总和,再将结果进行行列转换,输出格式如下:
city | Spring_Electronics | Summer_Clothing | Autumn_Books | Winter_Electronics |
---|---|---|---|---|
Beijing | 100 | 150 | 0 | 0 |
Shanghai | 80 | 0 | 60 | 0 |
Guangzhou | 0 | 200 | 0 | 90 |
SELECT
city,
SUM(CASE WHEN season = 'Spring' AND product_type = 'Electronics' THEN sales_quantity ELSE 0 END) AS Spring_Electronics,
SUM(CASE WHEN season = 'Summer' AND product_type = 'Clothing' THEN sales_quantity ELSE 0 END) AS Summer_Clothing,
SUM(CASE WHEN season = 'Autumn' AND product_type = 'Books' THEN sales_quantity ELSE 0 END) AS Autumn_Books,
SUM(CASE WHEN season = 'Winter' AND product_type = 'Electronics' THEN sales_quantity ELSE 0 END) AS Winter_Electronics
FROM
product_sales
GROUP BY
city;
题目🎯:不同店铺不同时间段的顾客消费金额统计与转换
有一张顾客消费表 customer_consumption
,结构如下:
store_id | time_period | customer_id | consumption_amount |
---|---|---|---|
1 | Morning | 101 | 200 |
1 | Afternoon | 102 | 300 |
2 | Morning | 103 | 150 |
2 | Evening | 104 | 250 |
3 | Afternoon | 105 | 400 |
3 | Evening | 106 | 350 |
要求先统计每个店铺在不同时间段的顾客消费金额总和,再将结果进行行列转换,输出格式如下:
store_id | Morning_amount | Afternoon_amount | Evening_amount |
---|---|---|---|
1 | 200 | 300 | 0 |
2 | 150 | 0 | 250 |
3 | 0 | 400 | 350 |
SELECT
store_id,
SUM(CASE WHEN time_period = 'Morning' THEN consumption_amount ELSE 0 END) AS Morning_amount,
SUM(CASE WHEN time_period = 'Afternoon' THEN consumption_amount ELSE 0 END) AS Afternoon_amount,
SUM(CASE WHEN time_period = 'Evening' THEN consumption_amount ELSE 0 END) AS Evening_amount
FROM
customer_consumption
GROUP BY
store_id;
这些题目都遵循先按一定条件进行聚合统计,再使用 CASE WHEN
结合 SUM
函数进行行列转换的思路~😄
题目🎯:学生成绩行列转换
有一张学生成绩表 student_scores
,记录了学生的考试科目和成绩,表结构如下:
student_id | subject | score |
---|---|---|
1 | Math | 90 |
1 | English | 85 |
1 | Physics | 88 |
2 | Math | 80 |
2 | English | 75 |
2 | Chemistry | 82 |
要求将每个学生的成绩按照科目进行行列转换,输出格式如下:
student_id | Math_score | English_score | Physics_score | Chemistry_score |
---|---|---|---|---|
1 | 90 | 85 | 88 | 0 |
2 | 80 | 75 | 0 | 82 |
SELECT
student_id,
SUM(CASE WHEN subject = 'Math' THEN score ELSE 0 END) AS Math_score,
SUM(CASE WHEN subject = 'English' THEN score ELSE 0 END) AS English_score,
SUM(CASE WHEN subject = 'Physics' THEN score ELSE 0 END) AS Physics_score,
SUM(CASE WHEN subject = 'Chemistry' THEN score ELSE 0 END) AS Chemistry_score
FROM
student_scores
GROUP BY
student_id;
题目🎯:员工考勤记录行列转换
有一张员工考勤表 attendance_record
,记录了员工每天的考勤状态,表结构如下:
employee_id | attendance_date | status |
---|---|---|
1 | 2025-01-01 | Present |
1 | 2025-01-02 | Absent |
1 | 2025-01-03 | Present |
2 | 2025-01-01 | Present |
2 | 2025-01-02 | Present |
2 | 2025-01-03 | Absent |
要求将员工的考勤记录转换为以日期为列,员工考勤状态为值的格式,输出格式如下:
employee_id | 2025-01-01 | 2025-01-02 | 2025-01-03 |
---|---|---|---|
1 | Present | Absent | Present |
2 | Present | Present | Absent |
SELECT
employee_id,
MAX(CASE WHEN attendance_date = '2025-01-01' THEN status END) AS '2025-01-01',
MAX(CASE WHEN attendance_date = '2025-01-02' THEN status END) AS '2025-01-02',
MAX(CASE WHEN attendance_date = '2025-01-03' THEN status END) AS '2025-01-03'
FROM
attendance_record
GROUP BY
employee_id;
题目🎯:订单商品分类统计行列转换
有一张订单商品表 order_products
,记录了订单中商品的类别和数量,表结构如下:
order_id | category | quantity |
---|---|---|
1001 | Food | 5 |
1001 | Beverage | 3 |
1001 | Household | 2 |
1002 | Food | 3 |
1002 | Beverage | 4 |
1003 | Household | 3 |
要求统计每个订单中不同商品类别的数量,并进行行列转换,输出格式如下:
order_id | Food_quantity | Beverage_quantity | Household_quantity |
---|---|---|---|
1001 | 5 | 3 | 2 |
1002 | 3 | 4 | 0 |
1003 | 0 | 0 | 3 |
SELECT
order_id,
SUM(CASE WHEN category = 'Food' THEN quantity ELSE 0 END) AS Food_quantity,
SUM(CASE WHEN category = 'Beverage' THEN quantity ELSE 0 END) AS Beverage_quantity,
SUM(CASE WHEN category = 'Household' THEN quantity ELSE 0 END) AS Household_quantity
FROM
order_products
GROUP BY
order_id;
好了好了 真的吃撑了哈哈哈哈哈🤣🤣🤣
整理不易 后续还会继续更新 希望列位多多支持~🚀🚀🚀