试图理解over()和partition by

时间:2012-02-16 16:29:24

标签: sql oracle

我正试图通过缠绕在我头上的功能进行分区。这是一个我不明白的例子。

以下是我的数据:

SALESORDERID       ORDERDATE 
43894              08/01/2001 
43664              07/01/2001 
43911              08/01/2001 
43867              08/01/2001 
43877              08/01/2001 
44285              10/01/2001 
44501              11/01/2001 
43866              08/01/2001 
43895              08/01/2001 
43860              08/01/2001

当我运行此查询时:

select Row_Number() over(partition by orderdate order by orderdate asc) 
    as Rownumber, salesorderid, orderdate
from test2
order by rownumber

以下是我得到的结果:

ROWNUMBER     SALESORDERID       ORDERDATE 
1             43664              07/01/2001 
1             43911              08/01/2001 
1             44109              09/01/2001 
1             44483              11/01/2001 
1             44285              10/01/2001 
2             43867              08/01/2001 
2             44501              11/01/2001 
3             43895              08/01/2001 
4             43894              08/01/2001 
5             43877              08/01/2001 

有人可以向我解释这个问题。我不是SQL的新手,但是我一直在苦苦挣扎,并且不能让我的头脑缠身。

2 个答案:

答案 0 :(得分:34)

尝试按订单日期排序,您会更轻松地看到结果

select Row_Number() over(partition by orderdate order by orderdate asc) 
    as Rownumber, salesorderid, orderdate
from test2
order by orderdate;

应该给(为了清晰起见我添加了空行)

ROWNUMBER     SALESORDERID       ORDERDATE
1             43664              07/01/2001

1             43911              08/01/2001
2             43867              08/01/2001
3             43895              08/01/2001
4             43894              08/01/2001
5             43877              08/01/2001

1             44109              09/01/2001

1             44285              10/01/2001

1             44483              11/01/2001
2             44501              11/01/2001

您会注意到结果被划分为“分区”,每个分区都是具有相同顺序的行集。这就是“按顺序分区”的含义。

在一个分区中,行按orderdate排序,按照'(按orderdate order by orderdate asc)'的第二个子句排序。这不是很有用,因为分区中的所有行都将具有相同的orderdate。因此,分区内行的排序是随机的。尝试使用partition by子句中的salesorderid进行排序,以获得更可重现的结果。

row_number()只返回每个分区中行的排序

答案 1 :(得分:12)

partition by orderdate表示您只是将记录与具有相同orderdate的其他记录进行比较。例如,在orderdate = '08/01/2001'的五个记录中,一个将有row_number() = 1,一个将有row_number() = 2,依此类推。

order by orderdate asc表示在分区内,行号将按orderdate的顺序分配。在您的示例中没有任何效果,因为您已经按orderdate进行分区,因此分区中的所有记录都将具有相同的orderdate。 (这就像写SELECT ... FROM t WHERE c = 6 ORDER BY c:所有选定的记录都具有c的相同值,因此ORDER BY c什么都不做。)因此,在一个分区中,{{1}的赋值}是任意的:每一行都有不同的数字,但不保证哪一行会有哪个数字。