在ORACLE中
Category表
CategoryId CategoryDESC
1 ...
2 ...Product表
ProductId CategoryId ProductDESC
101 1 AAA
102 1 BBB
103 1 CCC
104 2 DDD
105 2 EEE
106 2 FFF现要求一次性从product表中查出属于各个类别的前2条如:
ProductId CategoryId ProductDESC
101 1 AAA
102 1 BBB
104 2 DDD
105 2 EEE请指点。
Category表
CategoryId CategoryDESC
1 ...
2 ...Product表
ProductId CategoryId ProductDESC
101 1 AAA
102 1 BBB
103 1 CCC
104 2 DDD
105 2 EEE
106 2 FFF现要求一次性从product表中查出属于各个类别的前2条如:
ProductId CategoryId ProductDESC
101 1 AAA
102 1 BBB
104 2 DDD
105 2 EEE请指点。
(select ProductId,CategoryId,ProductDESC,row_number() over (partition by CategoryId order by sal ProductId) rn
from Product)
where rn<3
看不懂,能给小弟解释一吗?
转铁
这些都是分析函数,好像时8.0以后才有的
row_number()和rownum差不多,功能更强一点(可以在各个分组内从1开时排序)
rank()是跳跃排序,有两个第二名时接下来就是第四名(同样是在各个分组内)
dense_rank()l是连续排序,有两个第二名时仍然跟着第三名。
相比之下row_number是没有重复值的
lag(arg1,arg2,arg3):
arg1是从其他行返回的表达式
arg2是希望检索的当前行分区的偏移量。是一个正的偏移量,时一个往回检索以前的行的数目。
arg3是在arg2表示的数目超出了分组的范围时返回的值。
SQL> set pagesize 100;
SQL> select rownum from emp;ROWNUM
----------
1
2
3
4
5
6
7
8
9
10
11
12
13
14已选择14行。已用时间: 00: 00: 00.10
SQL> select deptno,row_number() over(partition by deptno order by sal) from emp order by deptno;
DEPTNO ROW_NUMBER()OVER(PARTITIONBYDEPTNOORDERBYSAL)
---------- ---------------------------------------------
10 1
2
320 1
2
3
4
530 1
2
3
4
5
6
已选择14行。已用时间: 00: 00: 00.41
SQL> select deptno,rank() over (partition by deptno order by sal) from emp order by deptno;DEPTNO RANK()OVER(PARTITIONBYDEPTNOORDERBYSAL)
---------- ---------------------------------------
10 1
2
320 1
2
3
4
430 1
2
2
4
5
6
已选择14行。已用时间: 00: 00: 00.21
SQL> select deptno,dense_rank() over(partition by deptno order by sal) from emp order by deptno;DEPTNO DENSE_RANK()OVER(PARTITIONBYDEPTNOORDERBYSAL)
---------- ---------------------------------------------
10 1
2
320 1
2
3
4
430 1
2
2
3
4
5
已选择14行。已用时间: 00: 00: 00.20
SQL> select deptno,ename,sal,lag(ename,1,null) over(partition by deptno order by ename) from emp ord
er by deptno;DEPTNO ENAME SAL LAG(ENAME,
---------- ---------- ---------- ----------
10 CLARK 2450
KING 5000 CLARK
MILLER 1300 KING20 ADAMS 1100
FORD 3000 ADAMS
JONES 2975 FORD
SCOTT 3000 JONES
SMITH 800 SCOTT30 ALLEN 1600
BLAKE 2850 ALLEN
JAMES 950 BLAKE
MARTIN 1250 JAMES
TURNER 1500 MARTIN
WARD 1250 TURNER
已选择14行。已用时间: 00: 00: 00.31
SQL> select deptno,ename,sal,lag(ename,2,'example') over(partition by deptno order by ename) from em
p order by deptno;DEPTNO ENAME SAL LAG(ENAME,
---------- ---------- ---------- ----------
10 CLARK 2450 example
KING 5000 example
MILLER 1300 CLARK20 ADAMS 1100 example
FORD 3000 example
JONES 2975 ADAMS
SCOTT 3000 FORD
SMITH 800 JONES30 ALLEN 1600 example
BLAKE 2850 example
JAMES 950 ALLEN
MARTIN 1250 BLAKE
TURNER 1500 JAMES
WARD 1250 MARTIN
已选择14行。已用时间: 00: 00: 00.30这下应该没问题了吧?格式
analytic_function OVER
(
[PARTITION BY value_expr]
[ ORDER BY expr [ASC/DESC] [NULLS FIRST/NULLS LAST]
[ROWS/RANGE BETWEEN UNBOUNDED PRECEDING/
CURRENT ROW/
value_expr PRECEDING/FOLLOWING
AND UNBOUNDED FOLLOWING/
CURRENT ROW/
value_expr PRECEDING/FOLLOWING
]
]
)
太复杂了,是吧?! 讲简单一点,分析函数是对查询结果的操作(多数为汇总类的函数)
其中:PARTITION BY子句用于分组(类似GROUP BY), 即在各个分组之内应用分析函数
ORDER BY子句用于在分组中排序
后面的一大串(即ROWS/RANGE BETWEEN...AND...)是对于每一行数据的分析范围 举几个例子: 1.
select empno, ename, deptno, sal,
sum(sal) over (partition by deptno order by ename) x
from scott.emp;
--注意PARTITION BY, ORDER BY 2.
select empno, ename, deptno, sal,
sum(sal) over (partition by deptno order by ename
rows between unbounded preceding and current row) x
from scott.emp;
--注意ROWS BETWEEN unbounded preceding AND current row
--是指第一行至当前行的汇总 3.
select empno, ename, deptno, sal,
sum(sal) over (partition by deptno order by ename
rows between current row and unbounded following) x
from scott.emp;
--注意ROWS BETWEEN current row AND unbounded following
--是指当前行到最后一行的汇总 4.
select empno, ename, deptno, sal,
sum(sal) over (partition by deptno order by ename
rows between 1 preceding and current row) x
from scott.emp;
--注意ROWS BETWEEN 1 preceding AND current row
--是指当前行的上一行(rownum-1)到当前行的汇总 5.
select empno, ename, deptno, sal,
sum(sal) over (partition by deptno order by ename
rows between 1 preceding and 2 following) x
from scott.emp;
--注意ROWS BETWEEN 1 preceding AND 1 following
--是指当前行的上一行(rownum-1)到当前行的下辆行(rownum+2)的汇总 row_number得到的是分组中的行号
rank得到的是分组中的排名,如果排序值相同,rank()值相同
dense_rank与rank相似,只是不会跳号 例:
select empno,sal,
row_number() over(order by sal) x,
rank() over(order by sal) y,
dense_rank() over(order by sal) z
from emp where deptno=30; EMPNO SAL X Y Z
----- -------- --- --- ---
7900 1500 1 1 1
7901 1500 2 1 1
7902 1600 3 3 2
7903 1700 4 4 3
7904 1700 5 4 3
7905 1700 6 4 3
7906 1800 7 7 4
7907 2000 8 8 5