Rownum是oracle提供的一个伪列,我们用的比较多的地方是在做分页的时候。
如果对rownum使用不当,往往会出现一些比较抓狂的现象。
假如有表结构如下:
tid? tname ttype
5??? T1??? Q1
4??? T4??? Q1
3??? T3??? Q7
2??? T2??? Q2
1??? T1??? Q6
6??? T6??? Q1
7??? T7??? Q3
8??? T8??? Q3
9??? T9??? Q4
10??? T10??? Q5
?
执行语句:SELECT rownum,t.* FROM t_test t ORDER BY t.tid;
预期的结果应该是:
rownum tid tname ttype
1??? 1??? T1??? Q6
2??? 2??? T2??? Q2
3??? 3??? T3??? Q7
4??? 4??? T4??? Q1
5??? 5??? T1??? Q1
6??? 6??? T6??? Q1
7??? 7??? T7??? Q3
8??? 8??? T8??? Q3
9??? 9??? T9??? Q4
10??? 10??? T10??? Q5
而真实结果确实:
rownum tid tname ttype
5??? 1??? T1??? Q6
4??? 2??? T2??? Q2
3??? 3??? T3??? Q7
2??? 4??? T4??? Q1
1??? 5??? T1??? Q1
6??? 6??? T6??? Q1
7??? 7??? T7??? Q3
8??? 8??? T8??? Q3
9??? 9??? T9??? Q4
10??? 10??? T10??? Q5
?
产生的结果并没有按我们预期的先排序再生成rownum值,生成的rownum值是按照我们添加数据时的顺序。
?
产生这种结果可以有两种方式解决:
1、order by 字段建立主键约束
2、将rownum提到外层使用,语句:
SELECT ROWNUM,tt.* FROM (
SELECT * FROM t_test t
)tt
?
采用这两种方式之一,输出的结果就同我们预想的一样。
?
但是,在使用的过程中发现了另外一个问题,在对分组字句使用rownum时显示乱序。
sql语句:
SELECT * FROM (
SELECT MAX(t.tid),MAX(t.tname),t.ttype FROM t_test t GROUP BY t.ttype
) tt WHERE ROWNUM<3
执行结果并没有如预期显示子查询结果的前两行数据。
?
解决方法有两个:
1、分组内部先排序
SELECT * FROM (
SELECT MAX(t.tid),MAX(t.tname),t.ttype FROM t_test t GROUP BY t.ttype ORDER BY MAX(t.tid)
) tt WHERE ROWNUM<3
2、分组外多包层查询
SELECT ttt.* FROM (
SELECT ROWNUM row_num,tt.* FROM (
SELECT MAX(t.tid),MAX(t.tname),t.ttype FROM t_test t GROUP BY t.ttype
) tt
) ttt WHERE ROWNUM<3
?