PARTITION RANGE SUBQUERY子查询消除

本文探讨了在Oracle Database 10g中如何利用不同类型的连接操作(如NESTED LOOPS、HASH JOIN 和 MERGE JOIN)来处理分区表,并讨论了在启用和禁用子查询消除的情况下执行计划的变化。

troubleshooting中的例子:

CREATE TABLE t ( id NUMBER, d1 DATE, n1 NUMBER, n2 NUMBER, n3 NUMBER, pad VARCHAR2(4000), CONSTRAINT t_pk PRIMARY KEY (id) ) PARTITION BY RANGE (n1, d1) ( PARTITION t_1_jan_2007 VALUES LESS THAN (1, to_date('2007-02-01','yyyy-mm-dd')), PARTITION t_1_feb_2007 VALUES LESS THAN (1, to_date('2007-03-01','yyyy-mm-dd')), PARTITION t_1_mar_2007 VALUES LESS THAN (1, to_date('2007-04-01','yyyy-mm-dd')), PARTITION t_1_apr_2007 VALUES LESS THAN (1, to_date('2007-05-01','yyyy-mm-dd')), PARTITION t_1_may_2007 VALUES LESS THAN (1, to_date('2007-06-01','yyyy-mm-dd')), PARTITION t_1_jun_2007 VALUES LESS THAN (1, to_date('2007-07-01','yyyy-mm-dd')), PARTITION t_1_jul_2007 VALUES LESS THAN (1, to_date('2007-08-01','yyyy-mm-dd')), PARTITION t_1_aug_2007 VALUES LESS THAN (1, to_date('2007-09-01','yyyy-mm-dd')), PARTITION t_1_sep_2007 VALUES LESS THAN (1, to_date('2007-10-01','yyyy-mm-dd')), PARTITION t_1_oct_2007 VALUES LESS THAN (1, to_date('2007-11-01','yyyy-mm-dd')), PARTITION t_1_nov_2007 VALUES LESS THAN (1, to_date('2007-12-01','yyyy-mm-dd')), PARTITION t_1_dec_2007 VALUES LESS THAN (1, to_date('2008-01-01','yyyy-mm-dd')), PARTITION t_2_jan_2007 VALUES LESS THAN (2, to_date('2007-02-01','yyyy-mm-dd')), PARTITION t_2_feb_2007 VALUES LESS THAN (2, to_date('2007-03-01','yyyy-mm-dd')), PARTITION t_2_mar_2007 VALUES LESS THAN (2, to_date('2007-04-01','yyyy-mm-dd')), PARTITION t_2_apr_2007 VALUES LESS THAN (2, to_date('2007-05-01','yyyy-mm-dd')), PARTITION t_2_may_2007 VALUES LESS THAN (2, to_date('2007-06-01','yyyy-mm-dd')), PARTITION t_2_jun_2007 VALUES LESS THAN (2, to_date('2007-07-01','yyyy-mm-dd')), PARTITION t_2_jul_2007 VALUES LESS THAN (2, to_date('2007-08-01','yyyy-mm-dd')), PARTITION t_2_aug_2007 VALUES LESS THAN (2, to_date('2007-09-01','yyyy-mm-dd')), PARTITION t_2_sep_2007 VALUES LESS THAN (2, to_date('2007-10-01','yyyy-mm-dd')), PARTITION t_2_oct_2007 VALUES LESS THAN (2, to_date('2007-11-01','yyyy-mm-dd')), PARTITION t_2_nov_2007 VALUES LESS THAN (2, to_date('2007-12-01','yyyy-mm-dd')), PARTITION t_2_dec_2007 VALUES LESS THAN (2, to_date('2008-01-01','yyyy-mm-dd')), PARTITION t_3_jan_2007 VALUES LESS THAN (3, to_date('2007-02-01','yyyy-mm-dd')), PARTITION t_3_feb_2007 VALUES LESS THAN (3, to_date('2007-03-01','yyyy-mm-dd')), PARTITION t_3_mar_2007 VALUES LESS THAN (3, to_date('2007-04-01','yyyy-mm-dd')), PARTITION t_3_apr_2007 VALUES LESS THAN (3, to_date('2007-05-01','yyyy-mm-dd')), PARTITION t_3_may_2007 VALUES LESS THAN (3, to_date('2007-06-01','yyyy-mm-dd')), PARTITION t_3_jun_2007 VALUES LESS THAN (3, to_date('2007-07-01','yyyy-mm-dd')), PARTITION t_3_jul_2007 VALUES LESS THAN (3, to_date('2007-08-01','yyyy-mm-dd')), PARTITION t_3_aug_2007 VALUES LESS THAN (3, to_date('2007-09-01','yyyy-mm-dd')), PARTITION t_3_sep_2007 VALUES LESS THAN (3, to_date('2007-10-01','yyyy-mm-dd')), PARTITION t_3_oct_2007 VALUES LESS THAN (3, to_date('2007-11-01','yyyy-mm-dd')), PARTITION t_3_nov_2007 VALUES LESS THAN (3, to_date('2007-12-01','yyyy-mm-dd')), PARTITION t_3_dec_2007 VALUES LESS THAN (3, to_date('2008-01-01','yyyy-mm-dd')), PARTITION t_4_jan_2007 VALUES LESS THAN (4, to_date('2007-02-01','yyyy-mm-dd')), PARTITION t_4_feb_2007 VALUES LESS THAN (4, to_date('2007-03-01','yyyy-mm-dd')), PARTITION t_4_mar_2007 VALUES LESS THAN (4, to_date('2007-04-01','yyyy-mm-dd')), PARTITION t_4_apr_2007 VALUES LESS THAN (4, to_date('2007-05-01','yyyy-mm-dd')), PARTITION t_4_may_2007 VALUES LESS THAN (4, to_date('2007-06-01','yyyy-mm-dd')), PARTITION t_4_jun_2007 VALUES LESS THAN (4, to_date('2007-07-01','yyyy-mm-dd')), PARTITION t_4_jul_2007 VALUES LESS THAN (4, to_date('2007-08-01','yyyy-mm-dd')), PARTITION t_4_aug_2007 VALUES LESS THAN (4, to_date('2007-09-01','yyyy-mm-dd')), PARTITION t_4_sep_2007 VALUES LESS THAN (4, to_date('2007-10-01','yyyy-mm-dd')), PARTITION t_4_oct_2007 VALUES LESS THAN (4, to_date('2007-11-01','yyyy-mm-dd')), PARTITION t_4_nov_2007 VALUES LESS THAN (4, to_date('2007-12-01','yyyy-mm-dd')), PARTITION t_4_dec_2007 VALUES LESS THAN (4, to_date('2008-01-01','yyyy-mm-dd')) ); execute dbms_random.seed(0) INSERT INTO t SELECT rownum AS id, trunc(to_date('2007-01-01','yyyy-mm-dd')+rownum/27.4) AS d1, 1+mod(rownum,4) AS n1, 255+mod(trunc(dbms_random.normal*1000),255) AS n2, round(4515+dbms_random.normal*1234) AS n3, dbms_random.string('p',255) AS pad FROM dual CONNECT BY level <= 10000 ORDER BY dbms_random.value; BEGIN dbms_stats.gather_table_stats( ownname => user, tabname => 'T', estimate_percent => 100, method_opt => 'for all columns size skewonly', cascade => TRUE ); END; / SELECT partition_name, partition_position, num_rows FROM user_tab_partitions WHERE table_name = 'T' ORDER BY partition_position; DROP TABLE tx; CREATE TABLE tx AS SELECT * FROM t; ALTER TABLE tx ADD CONSTRAINT tx_pk PRIMARY KEY (id); BEGIN dbms_stats.gather_table_stats( ownname => user, tabname => 'TX' ); END; / SQL> SELECT * FROM v$version WHERE rownum=1; BANNER ---------------------------------------------------------------- Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod --禁用子查询消除 ALTER SESSION SET "_subquery_pruning_enabled" = FALSE; SQL> set autotrace traceonly explain SQL> SQL> SELECT /*+ leading(tx) use_nl(t) */ * FROM tx, t WHERE tx.d1 = t.d1 AND tx.n1 = t.n1 AND tx.id = 19; 执行计划 ---------------------------------------------------------- Plan hash value: 2010553102 ------------------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | ------------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 7 | 3892 | 5 (0)| 00:00:01 | | | | 1 | NESTED LOOPS | | 7 | 3892 | 5 (0)| 00:00:01 | | | | 2 | TABLE ACCESS BY INDEX ROWID| TX | 1 | 278 | 2 (0)| 00:00:01 | | | |* 3 | INDEX UNIQUE SCAN | TX_PK | 1 | | 1 (0)| 00:00:01 | | | | 4 | PARTITION RANGE ITERATOR | | 7 | 1946 | 3 (0)| 00:00:01 | KEY | KEY | |* 5 | TABLE ACCESS FULL | T | 7 | 1946 | 3 (0)| 00:00:01 | KEY | KEY | ------------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("TX"."ID"=19) 5 - filter("TX"."D1"="T"."D1" AND "TX"."N1"="T"."N1") SQL> SELECT /*+ leading(tx) use_hash(t) */ * FROM tx, t WHERE tx.d1 = t.d1 AND tx.n1 = t.n1 AND tx.id = 19; 执行计划 ---------------------------------------------------------- Plan hash value: 1797314291 ------------------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | ------------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 7 | 3892 | 142 (2)| 00:00:02 | | | |* 1 | HASH JOIN | | 7 | 3892 | 142 (2)| 00:00:02 | | | | 2 | TABLE ACCESS BY INDEX ROWID| TX | 1 | 278 | 2 (0)| 00:00:01 | | | |* 3 | INDEX UNIQUE SCAN | TX_PK | 1 | | 1 (0)| 00:00:01 | | | | 4 | PARTITION RANGE ALL | | 10000 | 2714K| 139 (1)| 00:00:02 | 1 | 48 | | 5 | TABLE ACCESS FULL | T | 10000 | 2714K| 139 (1)| 00:00:02 | 1 | 48 | ------------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("TX"."D1"="T"."D1" AND "TX"."N1"="T"."N1") 3 - access("TX"."ID"=19) SQL> SELECT /*+ leading(tx) use_merge(t) */ * FROM tx, t WHERE tx.d1 = t.d1 AND tx.n1 = t.n1 AND tx.id = 19; 执行计划 ---------------------------------------------------------- Plan hash value: 3397819312 ------------------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | ------------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 7 | 3892 | 744 (1)| 00:00:09 | | | | 1 | MERGE JOIN | | 7 | 3892 | 744 (1)| 00:00:09 | | | | 2 | TABLE ACCESS BY INDEX ROWID| TX | 1 | 278 | 2 (0)| 00:00:01 | | | |* 3 | INDEX UNIQUE SCAN | TX_PK | 1 | | 1 (0)| 00:00:01 | | | |* 4 | FILTER | | | | | | | | | 5 | PARTITION RANGE ALL | | 10000 | 2714K| 139 (1)| 00:00:02 | 1 | 48 | | 6 | TABLE ACCESS FULL | T | 10000 | 2714K| 139 (1)| 00:00:02 | 1 | 48 | ------------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("TX"."ID"=19) 4 - filter("TX"."N1"="T"."N1" AND "TX"."D1"="T"."D1")在禁用子查询消除后,NESTED LOOPS 进行了分区消除,HASH JOIN与MERGE JOIN没有进行分区消除。--使用子查询消除 SQL> ALTER SESSION SET "_subquery_pruning_enabled" = TRUE; 会话已更改。 SQL> ALTER SESSION SET "_subquery_pruning_cost_factor"=1; 会话已更改。 SQL> ALTER SESSION SET "_subquery_pruning_reduction"=100; 会话已更改。 SQL> SELECT /*+ leading(tx) use_nl(t) */ * FROM tx, t WHERE tx.d1 = t.d1 AND tx.n1 = t.n1 AND tx.id = 19; 执行计划 ---------------------------------------------------------- Plan hash value: 2010553102 ------------------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | ------------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 7 | 3892 | 5 (0)| 00:00:01 | | | | 1 | NESTED LOOPS | | 7 | 3892 | 5 (0)| 00:00:01 | | | | 2 | TABLE ACCESS BY INDEX ROWID| TX | 1 | 278 | 2 (0)| 00:00:01 | | | |* 3 | INDEX UNIQUE SCAN | TX_PK | 1 | | 1 (0)| 00:00:01 | | | | 4 | PARTITION RANGE ITERATOR | | 7 | 1946 | 3 (0)| 00:00:01 | KEY | KEY | |* 5 | TABLE ACCESS FULL | T | 7 | 1946 | 3 (0)| 00:00:01 | KEY | KEY | ------------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("TX"."ID"=19) 5 - filter("TX"."D1"="T"."D1" AND "TX"."N1"="T"."N1") SQL> SELECT /*+ leading(tx) use_hash(t) */ * FROM tx, t WHERE tx.d1 = t.d1 AND tx.n1 = t.n1 AND tx.id = 19; 执行计划 ---------------------------------------------------------- Plan hash value: 4162004537 ------------------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | ------------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 7 | 3892 | 142 (2)| 00:00:02 | | | |* 1 | HASH JOIN | | 7 | 3892 | 142 (2)| 00:00:02 | | | | 2 | TABLE ACCESS BY INDEX ROWID| TX | 1 | 278 | 2 (0)| 00:00:01 | | | |* 3 | INDEX UNIQUE SCAN | TX_PK | 1 | | 1 (0)| 00:00:01 | | | | 4 | PARTITION RANGE SUBQUERY | | 10000 | 2714K| 139 (1)| 00:00:02 |KEY(SQ)|KEY(SQ)| | 5 | TABLE ACCESS FULL | T | 10000 | 2714K| 139 (1)| 00:00:02 |KEY(SQ)|KEY(SQ)| ------------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 1 - access("TX"."D1"="T"."D1" AND "TX"."N1"="T"."N1") 3 - access("TX"."ID"=19) SQL> SELECT /*+ leading(tx) use_merge(t) */ * FROM tx, t WHERE tx.d1 = t.d1 AND tx.n1 = t.n1 AND tx.id = 19; 执行计划 ---------------------------------------------------------- Plan hash value: 3857595143 ------------------------------------------------------------------------------------------------------ | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop | ------------------------------------------------------------------------------------------------------ | 0 | SELECT STATEMENT | | 7 | 3892 | 744 (1)| 00:00:09 | | | | 1 | MERGE JOIN | | 7 | 3892 | 744 (1)| 00:00:09 | | | | 2 | TABLE ACCESS BY INDEX ROWID| TX | 1 | 278 | 2 (0)| 00:00:01 | | | |* 3 | INDEX UNIQUE SCAN | TX_PK | 1 | | 1 (0)| 00:00:01 | | | |* 4 | FILTER | | | | | | | | | 5 | PARTITION RANGE SUBQUERY | | 10000 | 2714K| 139 (1)| 00:00:02 |KEY(SQ)|KEY(SQ)| | 6 | TABLE ACCESS FULL | T | 10000 | 2714K| 139 (1)| 00:00:02 |KEY(SQ)|KEY(SQ)| ------------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id): --------------------------------------------------- 3 - access("TX"."ID"=19) 4 - filter("TX"."N1"="T"."N1" AND "TX"."D1"="T"."D1")在开启子查询消除后,HASH JOIN与MERGE JOIN选择了PARTITION RANGE SUBQUERY,从Pstart| Pstop的KEY(SQ)也可以看出使用了子查询消除。

<think>好的,我现在需要给用户介绍SQL高级查询。首先,我得回忆一下自己学过的SQL知识,确保覆盖主要的高级查询技术。用户可能已经掌握了基础,比如SELECT、WHERE、JOIN这些,所以重点应该放在更复杂的部分。 首先想到的是子查询,包括相关子查询和非相关子查询。这部分需要解释清楚概念,并给出例子。比如在WHERE子句中使用子查询,或者在FROM子句中。然后是连接查询的进阶,比如自连接,自然连接,以及外连接的区别,特别是LEFT JOIN、RIGHT JOIN、FULL OUTER JOIN的应用场景。 接下来是集合操作,比如UNION、UNION ALL、INTERSECT和EXCEPT。这些操作符的作用和使用方法需要说明,同时要注意它们对结果集的影响,比如去重与否。 窗口函数也是高级查询的重要部分,得提到ROW_NUMBER()、RANK()、DENSE_RANK(),以及如何使用OVER子句进行分区和排序。比如计算每个部门的薪水排名,这样的例子比较典型。 CTE(公共表表达式)尤其是递归CTE的应用,比如处理层次结构数据。这部分可能需要详细一点的例子,比如组织架构或树状结构数据的查询。 接下来是分组和过滤的高级用法,比如GROUP BY的ROLLUP、CUBE和GROUPING SETS,这些用于生成多维汇总数据。同时,HAVING子句和WHERE的区别也需要强调,特别是对聚合条件的过滤。 分页查询也是一个实用技巧,不同数据库的实现可能不同,比如LIMIT/OFFSET、ROWNUM或者ROW_NUMBER()函数。需要指出这些方法在不同系统中的使用方式。 动态SQL虽然属于更高级的内容,但可以简要提及,说明其用途,比如根据条件构建查询字符串,但也要注意安全风险,比如SQL注入。 性能优化方面,索引的使用、执行计划的分析、避免全表扫描等要点需要提到。这部分帮助用户写出更高效的查询。 然后要检查是否有遗漏的部分,比如是否提到了DISTINCT、CASE语句的高级应用,或者像PIVOT这样的数据旋转操作?可能这些也属于高级技巧,但可能在基础部分已经涵盖,或者需要根据时间决定是否包含。 在结构上,需要分点清晰,每个部分用小标题,然后简要说明概念,给出示例代码。例如,子查询部分可以举一个例子,比如查找薪水高于平均值的员工,或者使用EXISTS的子查询。 同时,要确保LaTeX格式正确,数学表达式如变量名用$包围。比如,在解释分组函数时,如果有数学公式的话需要处理,但SQL示例代码本身不需要LaTeX,应该用代码块。不过用户要求中数学表达式用$...$,但SQL代码属于代码块,可能不需要,这点需要确认。但原指令中的例子是数学表达式,所以可能代码部分正常用反引号即可,而变量名在文中出现时用$符号,比如$column_name$。 另外,用户提到回答要结构清晰,逐步解决问题,所以可能需要按逻辑顺序组织内容,比如从子查询开始,再到连接、集合操作,然后是窗口函数、CTE,分组与过滤,分页,动态SQL,最后优化技巧。 最后需要验证每个知识点的正确性,比如递归CTE的语法是否正确,窗口函数的使用示例是否准确,避免给出错误的信息。比如递归CTE的例子是否能够正确展示层次查询,或者分页的LIMIT子句是否在MySQL和PostgreSQL中的正确用法。 总结下来,需要涵盖以下主要部分: 1. 子查询 2. 连接查询进阶 3. 集合操作 4. 窗口函数 5. 公共表表达式(CTE) 6. 高级分组与过滤 7. 分页查询 8. 动态SQL 9. 性能优化技巧 每个部分给出定义、用途、示例代码,并注意LaTeX格式的正确应用。同时确保用中文解释清楚,结构层次分明,用户容易理解。</think>### SQL 高级查询详解 SQL 高级查询是处理复杂数据操作的核心工具,以下按**结构逐步展开**,涵盖关键技术与示例: --- #### 一、子查询Subquery子查询是嵌套在主查询中的查询,分为**非相关子查询**(独立执行)和**相关子查询**(依赖外部查询)。 1. **WHERE 子句中的子查询** 示例:查找薪水高于平均值的员工 ```sql SELECT name, salary FROM employees WHERE salary > (SELECT AVG(salary) FROM employees); ``` 2. **FROM 子句中的子查询(派生表)** 示例:计算每个部门的平均薪水 ```sql SELECT dept_id, avg_salary FROM (SELECT dept_id, AVG(salary) AS avg_salary FROM employees GROUP BY dept_id) AS dept_avg; ``` 3. **EXISTS / NOT EXISTS** 示例:查找有订单的客户 ```sql SELECT customer_id FROM customers c WHERE EXISTS (SELECT 1 FROM orders o WHERE o.customer_id = c.customer_id); ``` --- #### 二、连接查询进阶 1. **自连接(Self Join)** 示例:查找同一部门的员工对 ```sql SELECT e1.name, e2.name FROM employees e1 JOIN employees e2 ON e1.dept_id = e2.dept_id AND e1.employee_id < e2.employee_id; ``` 2. **外连接(Outer Join)** - `LEFT JOIN`:包含左表所有记录,右表无匹配时填充 `NULL` - `FULL OUTER JOIN`:包含两表所有记录(部分数据库不支持) 示例:显示所有客户及订单(无订单的客户保留) ```sql SELECT c.name, o.order_id FROM customers c LEFT JOIN orders o ON c.customer_id = o.customer_id; ``` --- #### 三、集合操作 通过集合运算符合并多个查询结果: - `UNION`:去重合并 - `UNION ALL`:不去重合并 - `INTERSECT`:取交集 - `EXCEPT`:取差集 示例:合并两个查询结果 ```sql SELECT product_id FROM orders_2022 UNION SELECT product_id FROM orders_2023; ``` --- #### 四、窗口函数(Window Function) 对数据“窗口”进行计算,保留明细行的同时聚合结果。 语法: ```sql 函数名() OVER (PARTITION BY 列 ORDER BY 列 [ROWS/RANGE 子句]) ``` 常用函数: - `ROW_NUMBER()`:行号 - `RANK()`:排名(允许并列) - `SUM() OVER()`:累计求和 示例:计算每个部门内的薪水排名 ```sql SELECT name, dept_id, salary, RANK() OVER (PARTITION BY dept_id ORDER BY salary DESC) AS dept_rank FROM employees; ``` --- #### 五、公共表表达式(CTE) CTE 通过 `WITH` 定义临时结果集,提升可读性,支持递归查询。 1. **普通 CTE** 示例:查询部门平均薪水 ```sql WITH dept_avg AS ( SELECT dept_id, AVG(salary) AS avg_salary FROM employees GROUP BY dept_id ) SELECT * FROM dept_avg WHERE avg_salary > 10000; ``` 2. **递归 CTE** 示例:查询组织架构层级 ```sql WITH RECURSIVE org_tree AS ( SELECT employee_id, name, manager_id FROM employees WHERE manager_id IS NULL -- 根节点 UNION ALL SELECT e.employee_id, e.name, e.manager_id FROM employees e JOIN org_tree ot ON e.manager_id = ot.employee_id ) SELECT * FROM org_tree; ``` --- #### 六、高级分组与过滤 1. **GROUP BY 扩展** - `ROLLUP`:生成层次化小计 - `CUBE`:生成所有维度组合的小计 - `GROUPING SETS`:自定义分组集 示例:按部门和年份统计销售额 ```sql SELECT dept_id, YEAR(order_date) AS year, SUM(amount) FROM orders GROUP BY ROLLUP(dept_id, year); ``` 2. **HAVING 子句** 对聚合结果过滤(`WHERE` 过滤行,`HAVING` 过滤组)。 示例:筛选订单数超过 100 的客户 ```sql SELECT customer_id, COUNT(*) AS order_count FROM orders GROUP BY customer_id HAVING COUNT(*) > 100; ``` --- #### 七、分页查询 不同数据库语法差异: - **MySQL/PostgreSQL**: ```sql SELECT * FROM employees ORDER BY hire_date LIMIT 10 OFFSET 20; -- 跳过前20行,取10行 ``` - **SQL Server**: ```sql SELECT * FROM employees ORDER BY hire_date OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY; ``` --- #### 八、动态 SQL 在程序代码中拼接 SQL 语句(如使用变量控制条件),需注意防范 SQL 注入。 示例(Python): ```python query = "SELECT * FROM products WHERE category = %s" cursor.execute(query, (user_input_category,)) ``` --- #### 九、性能优化技巧 1. **使用索引**:为高频查询列(如 `WHERE`、`JOIN` 条件)创建索引。 2. **避免全表扫描**:减少 `SELECT *`,使用具体列名;优化复杂条件。 3. **分析执行计划**:通过 `EXPLAIN` 查看查询路径,优化慢步骤。 --- ### 总结 掌握高级查询技术可显著提升数据处理能力,重点在于: 1. 灵活使用子查询和连接处理复杂逻辑 2. 利用窗口函数实现高级分析 3. 通过 CTE 优化递归或分层查询 4. 结合性能优化原则编写高效 SQL
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值