在分析ORDER BY
函数中使用COUNT
子句时,我不明白为什么会有不同的结果。
使用一个简单的例子:
with req as
(select 1 as n, 'A' as cls
from dual
union
select 2 as n, 'A' as cls
from dual)
select req.*, count(*) over(partition by cls) as cnt from req;
给出以下结果:
N CLS CNT
2 A 2
1 A 2
然而,在分析子句中添加ORDER BY
时,结果会有所不同!
with req as
(select 1 as n, 'A' as cls
from dual
union
select 2 as n, 'A' as cls
from dual)
select req.*, count(*) over(partition by cls order by n) as cnt from req;
CNT栏改了:
N CLS CNT
1 A 1
2 A 2
有人可以解释一下吗?
由于
答案 0 :(得分:5)
首先,link到文档。然而,这有点模糊不清。
分析条款由query_partition_clause
,order_by_clause
和windowing_clause
组成。而且,关于windowing_clause
的一个非常重要的事情是
除非已指定,否则不能指定此子句
order_by_clause
。由RANGE
子句定义的一些窗口边界 让您只在order_by_clause
中指定一个表达式。参考 "对ORDER BY条款的限制"。
但是,如果没有windowing_clause
,你不仅可以使用order_by_clause
,而且它们是捆绑在一起的。
如果完全省略windowing_clause,则默认为
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
。
默认的窗口子句产生类似于运行总计的内容。 COUNT
为第一行返回1
,因为窗口顶部和当前行之间只有一行,第二行只有2
,依此类推。
因此,在您的第一个查询中,根本没有 no 窗口,但第二个窗口中存在默认窗口。
您可以通过指定完全无界的窗口来模拟第一个查询的行为。
with req as
(select 1 as n, 'A' as cls
from dual
union
select 2 as n, 'A' as cls
from dual)
select req.*, count(*) over(partition by cls order by n RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as cnt from req;
是的
N CLS CNT
1 A 2
2 A 2
答案 1 :(得分:3)
考虑这一点的最简单方法 - 让ORDER BY
离开等同于“排序”,使得分区中的所有行彼此“相等”。实际上,您可以通过显式添加ORDER BY
这样的ORDER BY 0
子句来获得相同的效果:ORDER BY NULL
(或“按”任何常量表达式排序),甚至更重要的是, COUNT()
。
为什么你得到整个分区的SUM()
或RANGE between unbounded preceding and current row
等与默认的窗口子句{{1}}有关。 “范围”(与“ROWS”相对)意味着所有与当前行“绑定”的行也包括在内,即使它们不在它之前。由于所有行都是绑定的,这意味着包含整个分区,无论哪一行是“当前行”。