使用和不使用 ORDER BY 子句的分区分析计数
Analytic count over partition with and without ORDER BY clause
我不明白为什么在解析 COUNT
函数中使用 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) 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
有人可以解释一下吗?
谢谢
首先,link 文档。然而,它有点模糊。
解析子句由query_partition_clause
、order_by_clause
和windowing_clause
组成。而且,关于 windowing_clause
的一个非常重要的事情是
You cannot specify this clause unless you have specified the
order_by_clause
. Some window boundaries defined by the RANGE
clause
let you specify only one expression in the order_by_clause
. Refer to
"Restrictions on the ORDER BY Clause".
但是,如果没有 order_by_clause
,您不仅不能使用 windowing_clause
,而且它们是捆绑在一起的。
If you omit the windowing_clause entirely, then the default is RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
.
默认的 windowing 子句产生类似 运行 的结果。 COUNT
returns 1
第一行,因为 window 的顶部和当前行之间只有一行,第二行 2
和等等。
因此在您的第一个查询中根本没有 windowing,但是在第二个查询中有默认的 windowing。
并且您可以通过指定完全无界来模拟第一个查询的行为window。
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
最简单的思考方式 - 将 ORDER BY
排除在外等同于 "ordering",分区中的所有行彼此 "equal"。实际上,您可以通过显式添加 ORDER BY
子句来获得相同的效果,如下所示:ORDER BY 0
(或 "order by" any 常量表达式),甚至, 更强调的是, ORDER BY NULL
.
为什么你得到整个分区的 COUNT()
或 SUM()
等与默认窗口子句有关:RANGE between unbounded preceding and current row
。 "Range"(与 "ROWS" 相对)意味着包含当前行的所有行 "tied" 也包括在内,即使它们不在当前行之前。由于所有行都绑定,这意味着整个分区都包括在内,无论哪一行是 "current."
Window 函数将对按(拆分)值的分区执行聚合,当您省略 ORDER BY
子句时,结果将类似于 GROUP BY
每行的输出。也可以省略 PARTITION BY
,在这种情况下只有一个分区包含所有行
当您将 ORDER BY
子句添加到 window 函数时,它将在同一分区内按后续顺序执行计算,并从不同的分区(值组)重新开始
在 ORDER BY
顺序中不明显的值被称为对等值,在 COUNT()
中,它们将具有与其最后一个对等值相同的计算结果,这将产生间隙以保持总计
我不明白为什么在解析 COUNT
函数中使用 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) 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
有人可以解释一下吗?
谢谢
首先,link 文档。然而,它有点模糊。
解析子句由query_partition_clause
、order_by_clause
和windowing_clause
组成。而且,关于 windowing_clause
的一个非常重要的事情是
You cannot specify this clause unless you have specified the
order_by_clause
. Some window boundaries defined by theRANGE
clause let you specify only one expression in theorder_by_clause
. Refer to "Restrictions on the ORDER BY Clause".
但是,如果没有 order_by_clause
,您不仅不能使用 windowing_clause
,而且它们是捆绑在一起的。
If you omit the windowing_clause entirely, then the default is
RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
.
默认的 windowing 子句产生类似 运行 的结果。 COUNT
returns 1
第一行,因为 window 的顶部和当前行之间只有一行,第二行 2
和等等。
因此在您的第一个查询中根本没有 windowing,但是在第二个查询中有默认的 windowing。
并且您可以通过指定完全无界来模拟第一个查询的行为window。
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
最简单的思考方式 - 将 ORDER BY
排除在外等同于 "ordering",分区中的所有行彼此 "equal"。实际上,您可以通过显式添加 ORDER BY
子句来获得相同的效果,如下所示:ORDER BY 0
(或 "order by" any 常量表达式),甚至, 更强调的是, ORDER BY NULL
.
为什么你得到整个分区的 COUNT()
或 SUM()
等与默认窗口子句有关:RANGE between unbounded preceding and current row
。 "Range"(与 "ROWS" 相对)意味着包含当前行的所有行 "tied" 也包括在内,即使它们不在当前行之前。由于所有行都绑定,这意味着整个分区都包括在内,无论哪一行是 "current."
Window 函数将对按(拆分)值的分区执行聚合,当您省略 ORDER BY
子句时,结果将类似于 GROUP BY
每行的输出。也可以省略 PARTITION BY
,在这种情况下只有一个分区包含所有行
当您将 ORDER BY
子句添加到 window 函数时,它将在同一分区内按后续顺序执行计算,并从不同的分区(值组)重新开始
在 ORDER BY
顺序中不明显的值被称为对等值,在 COUNT()
中,它们将具有与其最后一个对等值相同的计算结果,这将产生间隙以保持总计