SQL中WITH与IN的用法及优化教程

一、WITH语句基础用法

1.1 公用表表达式(CTE)

WITH语句通过定义临时结果集简化复杂查询,常用于分解多步骤查询逻辑:

-- 基础语法
WITH cte_name AS (
    SELECT column1, column2 FROM table WHERE condition
)
SELECT * FROM cte_name;

-- 示例:计算各区域销售额并筛选Top区域
WITH regional_sales AS (
    SELECT region, SUM(amount) AS total_sales
    FROM orders
    GROUP BY region
),
top_regions AS (
    SELECT region FROM regional_sales 
    WHERE total_sales > (SELECT SUM(total_sales)/10 FROM regional_sales)
)
SELECT o.region, o.product, SUM(o.quantity) 
FROM orders o
WHERE o.region IN (SELECT region FROM top_regions)
GROUP BY o.region, o.product;

特点

  • 支持递归查询(RECURSIVE关键字)

  • 可被多次引用,提升代码可读性

1.2 递归查询

通过UNION ALL实现层级遍历:

WITH RECURSIVE employee_hierarchy AS (
    SELECT id, manager_id FROM employees WHERE manager_id IS NULL
    UNION ALL
    SELECT e.id, e.manager_id 
    FROM employees e
    INNER JOIN employee_hierarchy eh ON e.manager_id = eh.id
)
SELECT * FROM employee_hierarchy;

应用场景:组织架构树形查询、图结构遍历


二、IN操作符深度解析

2.1 基本语法

SELECT * FROM table1 
WHERE column1 IN (value1, value2, ...);

2.2 性能对比

场景

IN表现

推荐替代方案

子查询结果集小

高效(先执行子查询)

JOIN更优

子查询结果集大

低效(全表扫描)

EXISTS更优

主表数据量大

全表扫描

EXISTS+索引

性能优化示例

-- 低效写法
SELECT * FROM orders 
WHERE customer_id IN (SELECT id FROM customers WHERE country='CN');

-- 优化1:JOIN替代
SELECT o.* FROM orders o
JOIN customers c ON o.customer_id = c.id 
WHERE c.country='CN';

-- 优化2:EXISTS替代
SELECT * FROM orders o
WHERE EXISTS (
    SELECT 1 FROM customers c 
    WHERE c.id=o.customer_id AND c.country='CN'
);

三、WITH与IN的组合应用

3.1 递归+条件过滤

WITH RECURSIVE product_tree AS (
    SELECT product_id, parent_id FROM products WHERE parent_id IS NULL
    UNION ALL
    SELECT p.product_id, p.parent_id 
    FROM products p
    JOIN product_tree pt ON p.parent_id = pt.product_id
)
SELECT * FROM product_tree 
WHERE product_id IN (SELECT id FROM top_products);

3.2 临时结果集复用

WITH filtered_orders AS (
    SELECT order_id FROM orders WHERE amount > 1000
)
SELECT customer.* 
FROM customers customer
WHERE customer.id IN (SELECT order_id FROM filtered_orders);

四、性能优化指南

4.1 索引策略

  • 为IN子查询的字段建立索引

  • 递归查询中为关联字段添加索引

4.2 执行计划分析

使用EXPLAIN观察:

EXPLAIN 
SELECT * FROM employees 
WHERE department_id IN (SELECT id FROM departments WHERE location='BJ');

重点关注:

  • type字段是否为refrange

  • rows扫描行数

  • Extra中的Using where提示

4.3 大数据量处理

数据量

优化方案

子查询>1万行

改用JOIN或临时表

频繁查询

创建物化视图

分布式场景

分片查询+结果聚合


五、数据库差异对比

特性

MySQL

PostgreSQL

SQL Server

递归查询支持

8.0+支持

全版本支持

2005+支持

临时表生命周期

会话级

事务级

批处理级

最佳实践

优先使用JOIN替代IN

推荐WITH递归处理树形结构

使用CTE优化复杂查询

典型错误规避

  • 避免在NOT IN中使用可能含NULL的子查询

  • 递归查询需设置终止条件(如depth < 10

  • 分布式数据库慎用跨节点CTE


通过合理组合WITH的查询复用能力和IN的条件筛选,可显著提升SQL可读性和执行效率。建议在实际开发中结合EXPLAIN分析执行计划,针对具体场景选择最优方案。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值