insert into DEMO.TEST(ID,NAME,AGE,ADDRESS) VALUES(1,'cx',1,'湖北');
insert into DEMO.TEST(ID,NAME,AGE,ADDRESS) VALUES(1,'cx',1,'湖北');
insert into DEMO.TEST(ID,NAME,AGE,ADDRESS) VALUES(1,'cx',0.1,'湖北');
insert into DEMO.TEST(ID,NAME,AGE,ADDRESS) VALUES(1,'cx',0.1,'湖北');
insert into DEMO.TEST(ID,NAME,AGE,ADDRESS) VALUES(1,'cx1',1,'湖北');
insert into DEMO.TEST(ID,NAME,AGE,ADDRESS) VALUES(1,'cx2',1,'湖北');
insert into DEMO.TEST(ID,NAME,AGE,ADDRESS) VALUES(1,'cx1',0.1,'湖北');
insert into DEMO.TEST(ID,NAME,AGE,ADDRESS) VALUES(1,'cx2',0.1,'湖北');
insert into DEMO.TEST(ID,NAME,AGE,ADDRESS) VALUES(1,'cx',1,'湖南');
insert into DEMO.TEST(ID,NAME,AGE,ADDRESS) VALUES(1,'cx',1,'长沙');
insert into DEMO.TEST(ID,NAME,AGE,ADDRESS) VALUES(1,'cx',0.1,'上海');
insert into DEMO.TEST(ID,NAME,AGE,ADDRESS) VALUES(1,'cx',0.1,'长沙');
insert into DEMO.TEST(ID,NAME,AGE,ADDRESS) VALUES(1,'cx1',1,'湖南');
insert into DEMO.TEST(ID,NAME,AGE,ADDRESS) VALUES(1,'cx2',1,'上海');
insert into DEMO.TEST(ID,NAME,AGE,ADDRESS) VALUES(1,'cx1',0.1,'长沙');
insert into DEMO.TEST(ID,NAME,AGE,ADDRESS) VALUES(1,'cx2',0.1,'上海');
例如这是一组数据,我们对其进行查询:
ID | NAME | AGE | ADDRESS |
---|---|---|---|
1 | cx | 1 | 湖北 |
1 | cx | 1 | 湖北 |
1 | cx | 0.1 | 湖北 |
1 | cx | 0.1 | 湖北 |
1 | cx1 | 1 | 湖北 |
1 | cx2 | 1 | 湖北 |
1 | cx1 | 0.1 | 湖北 |
1 | cx2 | 0.1 | 湖北 |
1 | cx | 1 | 湖南 |
1 | cx | 1 | 长沙 |
1 | cx | 0.1 | 上海 |
1 | cx | 0.1 | 长沙 |
1 | cx1 | 1 | 湖南 |
1 | cx2 | 1 | 上海 |
1 | cx1 | 0.1 | 长沙 |
1 | cx2 | 0.1 | 上海 |
由于数据没有完全能够标识其唯一性的,我们引入伪劣ROWNUM,来标识他们:
select ID,NAME,AGE,ADDRESS,ROWNUM FROM DEMO.TEST;
ID | NAME | AGE | ADDRESS | ROWNUM |
---|---|---|---|---|
1 | cx | 1 | 湖北 | 1 |
1 | cx | 1 | 湖北 | 2 |
1 | cx | 0.1 | 湖北 | 3 |
1 | cx | 0.1 | 湖北 | 4 |
1 | cx1 | 1 | 湖北 | 5 |
1 | cx2 | 1 | 湖北 | 6 |
1 | cx1 | 0.1 | 湖北 | 7 |
1 | cx2 | 0.1 | 湖北 | 8 |
1 | cx | 1 | 湖南 | 9 |
1 | cx | 1 | 长沙 | 10 |
1 | cx | 0.1 | 上海 | 11 |
1 | cx | 0.1 | 长沙 | 12 |
1 | cx1 | 1 | 湖南 | 13 |
1 | cx2 | 1 | 上海 | 14 |
1 | cx1 | 0.1 | 长沙 | 15 |
1 | cx2 | 0.1 | 上海 | 16 |
OVER(ORDER BY …)的意思是以按照某个字段排序,所以和直接对表的order by效果是一样的,但是over(order by …)并不能单独使用,我们这里先使用 ROW_NUMBER() OVER (ORDER BY .. ASC)
row_number()
:从1开始,为每一条分组记录返回一个数字;OVER (ORDER BY .. ASC)
: 按所给字段列进行升序排列select ID,NAME,AGE,ADDRESS,ROWNUM,row_number() over(ORDER BY age asc) FROM DEMO.TEST;
ID | NAME | AGE | ADDRESS | ROWNUM | ROW_NUMBER()OVER(ORDERBYAGEASC) |
---|---|---|---|---|---|
1 | cx2 | 0.1 | 湖北 | 8 | 1 |
1 | cx1 | 0.1 | 长沙 | 15 | 2 |
1 | cx | 0.1 | 长沙 | 12 | 3 |
1 | cx | 0.1 | 上海 | 11 | 4 |
1 | cx2 | 0.1 | 上海 | 16 | 5 |
1 | cx1 | 0.1 | 湖北 | 7 | 6 |
1 | cx | 0.1 | 湖北 | 4 | 7 |
1 | cx | 0.1 | 湖北 | 3 | 8 |
1 | cx2 | 1 | 上海 | 14 | 9 |
1 | cx1 | 1 | 湖南 | 13 | 10 |
1 | cx2 | 1 | 湖北 | 6 | 11 |
1 | cx1 | 1 | 湖北 | 5 | 12 |
1 | cx | 1 | 长沙 | 10 | 13 |
1 | cx | 1 | 湖南 | 9 | 14 |
1 | cx | 1 | 湖北 | 2 | 15 |
1 | cx | 1 | 湖北 | 1 | 16 |
对上述结果还是不太满意,我们想得到的是,将name值相同的放在一块展示,并且按照age进行排序,此时我们可以使用:
row_number() over(PARTITION BY .. ORDER BY .. asc)
来控制
PARTITION BY ..
:会按照指定的字段,把相同值的排在一起,分为一个块,也就是分组select ID,NAME,AGE,ADDRESS,ROWNUM,row_number() over(PARTITION BY name ORDER BY age asc) FROM DEMO.TEST;
ID | NAME | AGE | ADDRESS | ROWNUM | ROW_NUMBER()OVER(PARTITIONBYNAMEORDERBYAGEASC) |
---|---|---|---|---|---|
1 | cx | 0.1 | 湖北 | 3 | 1 |
1 | cx | 0.1 | 湖北 | 4 | 2 |
1 | cx | 0.1 | 长沙 | 12 | 3 |
1 | cx | 0.1 | 上海 | 11 | 4 |
1 | cx | 1 | 湖南 | 9 | 5 |
1 | cx | 1 | 湖北 | 2 | 6 |
1 | cx | 1 | 湖北 | 1 | 7 |
1 | cx | 1 | 长沙 | 10 | 8 |
1 | cx1 | 0.1 | 湖北 | 7 | 1 |
1 | cx1 | 0.1 | 长沙 | 15 | 2 |
1 | cx1 | 1 | 湖北 | 5 | 3 |
1 | cx1 | 1 | 湖南 | 13 | 4 |
1 | cx2 | 0.1 | 上海 | 16 | 1 |
1 | cx2 | 0.1 | 湖北 | 8 | 2 |
1 | cx2 | 1 | 湖北 | 6 | 3 |
1 | cx2 | 1 | 上海 | 14 | 4 |
上述排序结果虽然是我们想看到的,但是我们希望如果name项目age也相同的,希望他们的排序值能够一样,这样我们可以采用另外一种方法:ROWNUM,rank() over(PARTITION BY .. ORDER BY .. asc)
;
ROWNUM,rank()
: row_number()是按照分完组之后,组内从1开始的递增排序,而rank()是按照分完组之后,组内从1开始排序的同时会比较字段值是否一样,字段值一样的记录排序值也一样,排序值以该组第一个相同值在当前组内的具体位置确定select ID,NAME,AGE,ADDRESS,ROWNUM,rank() over(PARTITION BY name ORDER BY age asc) FROM DEMO.TEST;
ID | NAME | AGE | ADDRESS | ROWNUM | RANK()OVER(PARTITIONBYNAMEORDERBYAGEASC) |
---|---|---|---|---|---|
1 | cx | 0.1 | 湖北 | 3 | 1 |
1 | cx | 0.1 | 湖北 | 4 | 1 |
1 | cx | 0.1 | 长沙 | 12 | 1 |
1 | cx | 0.1 | 上海 | 11 | 1 |
1 | cx | 1 | 湖南 | 9 | 5 |
1 | cx | 1 | 湖北 | 2 | 5 |
1 | cx | 1 | 湖北 | 1 | 5 |
1 | cx | 1 | 长沙 | 10 | 5 |
1 | cx1 | 0.1 | 湖北 | 7 | 1 |
1 | cx1 | 0.1 | 长沙 | 15 | 1 |
1 | cx1 | 1 | 湖北 | 5 | 3 |
1 | cx1 | 1 | 湖南 | 13 | 3 |
1 | cx2 | 0.1 | 上海 | 16 | 1 |
1 | cx2 | 0.1 | 湖北 | 8 | 1 |
1 | cx2 | 1 | 湖北 | 6 | 3 |
1 | cx2 | 1 | 上海 | 14 | 3 |
可以看出上述确如我们预想的一样,但是如果我们希望,排序值也能保证连续的,那么可以使用:
dense_rank()
:dense_rank()是按照分完组之后,组内从1开始排序的同时会比较字段值是否一样,字段值一样的记录排序值也一样,排序值以前一个相同值为准进行排序select ID,NAME,AGE,ADDRESS,ROWNUM,dense_rank() over(PARTITION BY name ORDER BY age asc) FROM DEMO.TEST;
ID | NAME | AGE | ADDRESS | ROWNUM | DENSE_RANK()OVER(PARTITIONBYNAMEORDERBYAGEASC) |
---|---|---|---|---|---|
1 | cx | 0.1 | 湖北 | 3 | 1 |
1 | cx | 0.1 | 湖北 | 4 | 1 |
1 | cx | 0.1 | 长沙 | 12 | 1 |
1 | cx | 0.1 | 上海 | 11 | 1 |
1 | cx | 1 | 湖南 | 9 | 2 |
1 | cx | 1 | 湖北 | 2 | 2 |
1 | cx | 1 | 湖北 | 1 | 2 |
1 | cx | 1 | 长沙 | 10 | 2 |
1 | cx1 | 0.1 | 湖北 | 7 | 1 |
1 | cx1 | 0.1 | 长沙 | 15 | 1 |
1 | cx1 | 1 | 湖北 | 5 | 2 |
1 | cx1 | 1 | 湖南 | 13 | 2 |
1 | cx2 | 0.1 | 上海 | 16 | 1 |
1 | cx2 | 0.1 | 湖北 | 8 | 1 |
1 | cx2 | 1 | 湖北 | 6 | 2 |
1 | cx2 | 1 | 上海 | 14 | 2 |