SQL难点突破之复杂业务逻辑的SQL查询实战
复杂业务逻辑SQL查询的核心挑战
处理多表关联、聚合计算、子查询嵌套时容易出现性能瓶颈和逻辑混乱,需掌握分层构建和优化技巧。
多表关联的精准控制
使用显式JOIN替代隐式连接,明确关联条件避免笛卡尔积。通过索引优化关联字段,例如为外键添加B-Tree索引。对于大型表关联,考虑先过滤再关联:
SELECT o.order_id, c.customer_name FROM orders o JOIN customers c ON o.customer_id = c.id WHERE o.create_time > \'2023-01-01\' -- 先筛选订单再关联
分层聚合与临时结果集
复杂统计分阶段计算,利用CTE (Common Table Expression) 或临时表分解逻辑。统计每月订单总金额及TOP3客户:
WITH monthly_stats AS ( SELECT DATE_TRUNC(\'month\', order_date) AS month, customer_id, SUM(amount) AS total_amount FROM orders GROUP BY 1, 2)SELECT month, customer_id, total_amount, RANK() OVER (PARTITION BY month ORDER BY total_amount DESC) AS rankFROM monthly_statsQUALIFY rank <= 3
窗口函数的进阶应用
处理行间关系时使用窗口函数避免自连接。计算移动平均或累计占比:
SELECT product_id, sale_date, daily_sales, AVG(daily_sales) OVER (PARTITION BY product_id ORDER BY sale_date ROWS 6 PRECEDING) AS 7day_avgFROM sales
动态条件构建技巧
使用CASE WHEN实现条件聚合,处理多维度指标计算。统计不同价格区间的商品数量:
SELECT category, COUNT(CASE WHEN price < 100 THEN 1 END) AS low_price, COUNT(CASE WHEN price BETWEEN 100 AND 500 THEN 1 END) AS mid_priceFROM productsGROUP BY category
递归查询解决层次结构
处理树形数据时使用递归CTE,例如组织架构或分类层级查询:
WITH RECURSIVE org_tree AS ( SELECT id, name, parent_id, 1 AS level FROM organization WHERE parent_id IS NULL UNION ALL SELECT o.id, o.name, o.parent_id, t.level + 1 FROM organization o JOIN org_tree t ON o.parent_id = t.id)SELECT * FROM org_tree ORDER BY level
执行计划分析与优化
通过EXPLAIN ANALYZE识别性能瓶颈,关注全表扫描和排序操作。对于大表分页使用延迟关联:
SELECT t.* FROM table tJOIN (SELECT id FROM table WHERE condition ORDER BY col LIMIT 10000, 10) tmpON t.id = tmp.id
将多行数据整合成一行数据
使用函数
GROUP_CONCAT(fee_id ORDER BY create_time SEPARATOR \',\') ,
GROUP_CONCAT 函数的主要作用就是将多行数据合并成一行字符串,常用于分组聚合后,将某一列的多个值拼接成一个字段。
✅GROUP_CONCAT` 的基本用法:
SELECT GROUP_CONCAT(name) AS namesFROM usersWHERE status = \'active\';
如果有多条
name
结果,会变成:\'张三,李四,王五\'
常用于 GROUP BY
的场景:
SELECT department_id, GROUP_CONCAT(employee_name) AS employeesFROM employeesGROUP BY department_id;
这会将每个部门下的员工名字拼成一行。
可选参数:
-
自定义分隔符:
GROUP_CONCAT(name SEPARATOR \'|\')
-
去重:
GROUP_CONCAT(DISTINCT name)
-
排序:
GROUP_CONCAT(name ORDER BY name DESC)
注意事项:
- 默认最大长度限制为
1024
字节(可以通过group_concat_max_len
调整)。 - 只能用于
MySQL
,PostgreSQL
中类似功能为STRING_AGG()
,Oracle
用LISTAGG()
。
GROUP_CONCAT()
就是把“多行变一行”的神器,常见于做报表或数据整合时使用。
如果你有具体的 SQL 场景,我可以帮你写个例子。