Subquery Factoring 子查询分解
(page 305)
Jared Still
You may not be familiar with the term subquery factoring . Prior to the release of Oracle 11gR2, the
official Oracle documentation barely mentions it, providing just a brief synopsis
of its use, a couple of
restrictions, and a single example. If I instead refer to the WITH clause of the SELECT statement, you will probably know immediately what I mean as this term is more recognizable. Both terms will be used in
this chapter.
你可能不熟悉术语“子查询分解”。在Oracle11gR2发行之前,Oracle官方文档很少提及它,只是提供了它使用的简要大纲
,一些限制条件,和一个例子。如果我是指SELECT语句的WITH子句,你可能马上明白我的意思了,因为这个术语很熟悉。在本章中两个术语都用到了。
With the release of Oracle 11gR2 (version 11.2), the WITH clause was enhanced with the ability to
recurse; that is, the factored subquery is allowed to call itself within some limitation. The value of this
may not be readily apparent. If you have used the CONNECT BY clause to create hierarchical queries, you will appreciate that recursive subqueries allow the same functionality to be implemented in an ANSI
standard format.
随着Oracle11gR2的发布(版本11.2),WITH子句增强了递归的能力,就是,分解的子查询允许在某些限定内调用自身。这点的价值可能不是那么明显。如果你使用CONNECT BY子句创建等级查询,你就会赞赏递归子查询,允许用ANSI标准格式执行相同的功能。
If the term subquery factoring is not known to you, perhaps you have heard of the ANSI Standard
term common table expression
(commonly called CTE). Common table expressions were first specified
in the 1999 ANSI SQL Standard. For some reason, Oracle has chosen to obfuscate
this name. Other
database vendors refer to common table expressions, so perhaps Oracle chose subquery factoring just to
be different.
如果数据子查询分解不为你熟知,可能你听说过ANSI标准数据公有表表达式
(一般称之为CTE)。公有表表达式首次在1999 ANSI
SQL标准中规定。由于某些原因,Oracle选择混淆
这个名字。其他的数据厂商指公有表表达式,因此可能Oracle选择子查询分解只是为了有所区别。
注: Factoring 在数学上的意思是“因式分解” ,
以后均简称“分解”。pivot本意是“绕...旋转”,但是很多书将这里的PIVOT翻译成“转置”,使人同线性代数中的转置(transpose)混淆,实际上两个不同的概念。本人喜欢直接称之为"旋转"。
PIVOT参考:http://www.oracle.com/technetwork/cn/articles/11g-pivot-101924-zhs.html
http://www.cnblogs.com/tracy/archive/2011/08/24/2151613.html
Standard Usage 标准用法
One of the most useful features of the WITH clause when it was first introduced was to cleanup complex SQL queries. When a large number of tables and columns are involved in a query, it can become difficult to follow the flow of data through the query. Via the use of subquery factoring, a query can be made more understandable by moving some of the complexity away from the main body of the query.
WITH子句最有用的特性之一就是它的引入首先清理复杂的SQL查询。当查询中涉及大量的表和列,把握查询的数据的流向就变得困难了。通过使用子查询分解,把一些复杂部分移出查询主体,使得查询变得更好理解。
The query in Listing 10-1 generates a crosstab report using the PIVOT operator. The formatting helps
make the SQL somewhat readable, but there is quite a bit going on here. The innermost query is creating
a set of aggregates on key sales columns, while the next most outer query simply provides column names
that are presented to the PIVOT operator, where the final values of sales by channel and quarter for each product are generated.
在列表10-1中的查询生成一交叉表报告使用PIVOT操作符。格式化有助于SQL更可读,但是还是很长。最里面的查询创建一组聚合在键sales
列上,而次外层查询简单的提供列名给PIVOT操作符,生成每款产品(product)按渠道(channel)和季度(quarter)分的销售
(sales)的最终值。
Listing 10-1. Crosstab without Subquery Factoring 没有子查询分解的交叉表
select *
from (
select /*+ gather_plan_statistics */
product
, channel
, quarter
, country
, quantity_sold
from
(
select
prod_name product
, country_name country
, channel_id channel
, substr(calendar_quarter_desc, 6,2) quarter
, sum(amount_sold) amount_sold
, sum(quantity_sold) quantity_sold
from
sh.sales
join sh.times on times.time_id = sales.time_id
join sh.customers on customers.cust_id = sales.cust_id
join sh.countries on countries.country_id = customers.country_id
join sh.products on products.prod_id = sales.prod_id
group by
prod_name
, country_name
, channel_id
, substr(calendar_quarter_desc, 6, 2)
)
) PIVOT
(
sum(quantity_sold)
FOR (channel, quarter) IN
(
(5, '02') AS CATALOG_Q2,
(4, '01') AS INTERNET_Q1,
(4, '04') AS INTERNET_Q4,
(2, '02') AS PARTNERS_Q2,
(9, '03') AS TELE_Q3
)
)
order by product, country;
Now let’s use the WITH clause to break the query in byte-sized chunks that are easier to comprehend. The SQL has been rewritten in Listing 10-2 using the WITH clause to create three subfactored queries, named sales_countries , top_sales , and sales_rpt . Notice that both the top_sales and sales_rpt subqueries are referring to other subqueries by name, as if they were a table or a view. By choosing names that make the of each subquery easy to follow, the readability of the SQL is improved. For instance, the subquery name sales_countries refers to the countries in which the sales took place, top_sales collects the sales data, and the sales_rpt subquery aggregates the data. The results of the sales_rpt subquery are used in the main query which answers the question, “What is the breakdown of sales by product and country per quarter?”
If you were not told the intent of the SQL in Listing 10-1, it would take some time to discern its purpose; on the other hand, the structure of the SQL in Listing 10-2 with subfactored queries makes it easier to understand the intent of the code.
现在让我们使用WITH子句将查询分解成字节大小的块,容易理解。在列表10-2中SQL用WITH语句重写,创建了三个子查询,名为
sales_countries , top_sales , 和sales_rpt。注意子查询top_sales 和sales_rpt
两者都按名称引用了其它的子查询,好像它们是一个表或者视图。通过选择适当的名称使得每个子查询容易理解,SQL的可读性也提高了。例如,子查询名为
sales_countries
指的是销售发生的国家,top_sales收集销售额数据,而sales_rpt子查询聚集数据。子查询sales_rpt
的结果用于主查询回答问题,“每季度按产品和国家分的销售额明细是什么?”
如果你没有告知列表10-1中SQL的意图,将花费好些时间领悟它的意思;另一方面,在列表10-2中的SQL结构带有分解的子查询使得它的代码更容易被理解。
In addition, the statements directly associated with the PIVOT operator are in the same section of the SQL statement at the bottom, further enhancing readability.
再者,语句直接关联了PIVOT操作符,在SQL语句的底部相同的段。进一步增加了可读性。
Listing 10-2. Crosstab with Subquery Factoring 带子查询因子的交叉表
with sales_countries as
(
select /*+ gather_plan_statistics */
cu.cust_id
, co.country_name
from sh.countries co, sh.customers cu
where cu.country_id = co.country_id
),
top_sales as
(
select
p.prod_name
, sc.country_name
, s.channel_id
, t.calendar_quarter_desc
, s.amount_sold
, s.quantity_sold
from
sh.sales s
join sh.times t on t.time_id = s.time_id
join sh.customers c on c.cust_id = s.cust_id
join sales_countries sc on sc.cust_id = c.cust_id
join sh.products p on p.prod_id = s.prod_id
),
sales_rpt as
(
select
prod_name product
, country_name country
, channel_id channel
, substr(calendar_quarter_desc, 6,2) quarter
, sum(amount_sold) amount_sold
, sum(quantity_sold) quantity_sold
from top_sales
group by
prod_name
, country_name
, channel_id
, substr(calendar_quarter_desc, 6, 2)
)
select * from
(
select product, channel, quarter, country, quantity_sold
from sales_rpt
) pivot
(
sum(quantity_sold)
for (channel, quarter) in
(
(5, '02') as catalog_q2,
(4, '01') as internet_q1,
(4, '04') as internet_q4,
(2, '02') as partners_q2,
(9, '03') as tele_q3
)
)
order by product, country;
While this is not an extremely complex SQL example, it does serve to illustrate the point of how the
WITH clause can be used to make a statement more readable and easier to maintain. Large complex
queries can be made more understandable by using this technique.
虽然这不是一个极其复杂的SQL例子,但是它示例出WITH语句如何能够使得语句更可读和容易维护。大而复杂的查询可通过使用这种技术变得更为可理解。
分享到:
相关推荐
《Pro Oracle SQL》是Oracle数据库查询的一本权威指南,其中Chapter 9深入探讨了SQL查询的各种高级技巧。在9.11章节中,主要讲解了Subquery Factoring,也被称为Common Table Expression(CTE),这是一个非常实用且...
提供的文件"Listing 10-10.sql"和"Listing 10-10_oracle.sql"很可能展示了如何在标准SQL和Oracle特有语法下使用Subquery Factoring的例子。在Oracle SQL中,我们可以在`WITH`子句后定义一个或多个子查询,每个子查询...
《Pro Oracle SQL》是Oracle数据库查询的一本权威指南,其中第二章主要讲解SQL查询的高级技巧。在2.8节“子查询展开(Subquery Unnesting)”中,我们将会深入探讨Oracle SQL中一种优化查询性能的重要策略。这一部分...
Pro Oracle SQL unlocks the power of SQL in the Oracle Database—one of the most potent SQL implementations on the market today. To master it requires a three-pronged approach: learn the language ...
Using a Subquery in the FROM Clause 4-10 Scalar Subquery Expressions 4-11 Scalar Subqueries: Examples 4-12 Correlated Subqueries 4-14 Using Correlated Subqueries 4-16 Using the EXISTS Operator 4-18 ...
### Oracle SQL Recipes: A Problem-Solution Approach #### 核心知识点概述 《Oracle SQL Recipes: A Problem-Solution Approach》是一本面向Oracle SQL开发者和技术人员的专业书籍。本书通过一系列实际问题和...
本资料“oracle-function--api.zip”包含了Oracle数据库中的一些核心API和SQL函数,特别是针对字符串、日期和数字类型的处理,对于Oracle开发人员来说极具参考价值。 一、Oracle SQL API Oracle SQL API是Oracle...
Java笔记--Oracle中SQL不能用Limit的处理 在Java开发中,我们经常需要对数据库进行分页查询,但是Oracle数据库不支持Limit关键字,那么如何在Oracle中实现分页查询呢?下面,我们将详细介绍Oracle中SQL不能用Limit...
- 使用“Exists”代替“In”子查询,或利用“Subquery Factoring”(WITH子句)来重用子查询结果。 6. **分组和排序优化** - `GROUP BY`和`ORDER BY`操作可能导致临时表和额外的排序,优化这些操作可以节省大量...
【Oracle数据库学习(一)-数据库原理及SQL】 在信息技术领域,数据库是不可或缺的一部分,它为数据的存储、管理和分析提供了高效且可靠的解决方案。本文主要介绍数据库的基本原理,特别是关系数据库,以及主流的...
Oracle扫盲-第一讲-创建和管理表PPT课件 本资源主要讲述Oracle数据库管理系统的基本知识,包括创建和管理表的方法、数据类型、CREATE TABLE语句、数据字典等。 知识点1:数据类型 Oracle数据库中有多种数据类型,...
在IT领域,SQL(Structured Query Language)是数据库管理和数据操作的核心语言。对于任何希望从事数据库管理、数据分析或软件开发的人来说,掌握SQL都是至关重要的。"SQL经典面试题---不错哦"这个主题涵盖了多个SQL...
子查询是在一个SQL查询中嵌套另一个完整的SQL查询,它可以作为选择、比较或者联接的数据源。在Laravel的Eloquent中,可以使用`DB::raw()`方法创建子查询。Eloquent Subquery Magic则提供了更高级的API,使得子查询...
Oracle SQL 是一种强大的数据库查询语言,用于从关系型数据库中检索、更新和管理数据。本实例主要探讨了如何使用复杂的查询语句,包括子查询和外连接,来处理多表查询。 1. 子查询(Subquery) 子查询是嵌套在其他...
《Oracle SQL Reference 9i+10g》是Oracle公司为数据库管理员、开发人员和分析师提供的官方SQL查询语言指南,涵盖了9i和10g两个重要版本。这两个版本的SQL特性在很多方面都有所增强,使得数据库管理和开发更加高效...
《专业Oracle SQL》一书由Karen Morton、Kerry Osborne、Robyn Sands、Riyaj Shamsudeen和Jared Still联合编写,旨在深入探讨Oracle数据库中的SQL语言及其支持功能,帮助读者全面掌握并充分利用SQL的强大能力。...
Oracle SQL基础培训旨在帮助初学者掌握Oracle数据库系统中的SQL语言,这是进行数据库管理和开发的关键技能。Oracle SQL是一种用于管理Oracle数据库中的数据的标准编程语言,它包括数据定义语言(DDL)、数据操纵语言...
本压缩包“oracle常用经典sql查询.rar”显然是一份关于如何在Oracle环境中高效运用SQL查询的教程资料,适合数据库管理员、开发人员以及对Oracle数据库感兴趣的用户学习。 首先,我们来探讨SQL的基础概念。SQL,全称...
在深入探讨《Oracle SQL高级编程》这一主题时,我们应当关注的是Oracle数据库系统中的SQL语言高级应用技巧,以及如何利用这些技巧来优化查询性能、增强数据处理能力,并实现更为复杂的数据分析需求。以下是对该主题...