两个分析查询之间的差异

时间:2009-08-04 17:07:58

标签: sql oracle

以下两个查询之间的差异是什么?两者都返回不同的行:

with ordered_table as 
(
select * from table order by column1
)
select first_value(column2 ignore nulls) over (partition by column3)
from ordered_table;

select first_value(column2 ignore nulls) over (partition by column3 order by column1)
from table;

注意:我会尝试提供测试用例,但我认为对于那些概念明确的人来说并不需要。

3 个答案:

答案 0 :(得分:0)

column1的排序在第一个查询中并没有真正做任何事情。

它按顺序创建一个结果集,但我不认为它会进入你的分区语句。 排序属于实际的分区子句。

答案 1 :(得分:0)

第一个版本对column1设置的整行进行排序,然后按column3对其进行分区并进行分析计算。请注意,column1的初始排序不一定通过分区保留 - 我认为这可能会让你感到困惑。

第二个版本按列3对数据进行分区,然后按列1对每个分区进行排序,然后确定分析输出。

答案 2 :(得分:0)

WITH ordered_table AS
        (
        SELECT  *
        FROM    table
        ORDER BY
                column1
        )
SELECT  FIRST_VALUE(column2 IGNORE NULLS) OVER (PARTITION BY column3)
FROM    ordered_table

此查询将以无特定顺序返回column2的第一个每分区值(即CBO可以自由选择其认为最佳的任何顺序。)

SELECT  FIRST_VALUE(column2 IGNORE NULLS) OVER (PARTITION BY column3 ORDER BY column1)
FROM    table;

此查询将返回column2的第一个每分区值,分区按column1排序。

由于SQL语言对集合进行操作,并且ORDER BY子句对CTE中返回的集合不执行任何操作,Oracle只忽略ORDER BY部分

CBO可以选择在外部查询使用CTE之前实现,哈希或以任何其他方式毁掉ORDER BY,因此CTE中使用的{{1}}将会{因外部查询而丢失。