只收集排版以备查,未验证,请知悉。
原作者: kelvin19840813
出处:http://www.cnblogs.com/kelvin19840813/articles/5701017.html
1. row_number over(order by sal)的实现 Row_number函数返回一个唯一的值,当碰到相同数据时,排名按照记录集中记录的顺序依次递增。
select empno, ename, sal, deptno, @rn := @rn + 1 as rn
from (select empno, ename, sal, deptno
from emp e, (select @rn := 0) b
order by e.sal desc) c;
+-------+--------+------+--------+------+ | empno | ename | sal | deptno | rn | +-------+--------+------+--------+------+ | 7839 | KING | 5000 | 10 | 1 | | 7902 | FORD | 3000 | 20 | 2 | | 7566 | JONES | 2975 | 20 | 3 | | 9999 | BLAKE | 2850 | 10 | 4 | | 7698 | BLAKE | 2850 | 30 | 5 | | 7782 | CLARK | 2450 | 10 | 6 | | 7499 | ALLEN | 1600 | 30 | 7 | | 7844 | TURNER | 1500 | 30 | 8 | | 7934 | MILLER | 1300 | 10 | 9 | | 7654 | MARTIN | 1250 | 30 | 10 | | 7876 | ADAMS | 1100 | 20 | 11 | | 7900 | JAMES | 950 | 30 | 12 | | 7369 | SMITH | 800 | 20 | 13 | +-------+--------+------+--------+------+
2. dense_rank over(order by sal)的实现 Dense_rank函数返回一个唯一的值,除非当碰到相同数据时,此时所有相同数据的排名都是一样的。
select empno,
ename,
sal,
deptno,
if(@sal = sal, @rn := @rn, @rn := @rn + 1) as dense_rank,
@sal := sal
from (select empno, ename, sal, deptno
from emp e, (select @rn := 0, @sal := 0) b
order by sal desc) c;
+-------+--------+------+--------+------------+-------------+ | empno | ename | sal | deptno | dense_rank | @sal := sal | +-------+--------+------+--------+------------+-------------+ | 7839 | KING | 5000 | 10 | 1 | 5000 | | 7902 | FORD | 3000 | 20 | 2 | 3000 | | 7566 | JONES | 2975 | 20 | 3 | 2975 | | 9999 | BLAKE | 2850 | 10 | 4 | 2850 | | 7698 | BLAKE | 2850 | 30 | 5 | 2850 | | 7782 | CLARK | 2450 | 10 | 6 | 2450 | | 7844 | TURNER | 1500 | 30 | 7 | 1500 | | 7934 | MILLER | 1300 | 10 | 8 | 1300 | | 7654 | MARTIN | 1250 | 30 | 9 | 1250 | | 7499 | ALLEN | 1250 | 30 | 9 | 1250 | | 7876 | ADAMS | 1100 | 20 | 10 | 1100 | | 7900 | JAMES | 950 | 30 | 11 | 950 | | 7369 | SMITH | 800 | 20 | 12 | 800 | +-------+--------+------+--------+------------+-------------+
3. rank over(order by sal)的实现 Rank函数返回一个唯一的值,除非遇到相同的数据时,此时所有相同数据的排名是一样的, 同时会在最后一条相同记录和下一条不同记录的排名之间空出排名。
select empno,
ename,
sal,
deptno,
if(@sal = sal, @rn := @rn, @rn := @rn + 1 + @i) as RANK,
if(@sal = sal, @i := @i + 1, @i := 0) as ii,
@sal := sal
from (select empno, ename, sal, deptno
from emp e, (select @rn := 0, @sal = 0, @i := 0) b
order by sal desc) c;
+-------+--------+------+--------+------+------+-------------+ | empno | ename | sal | deptno | RANK | ii | @sal := sal | +-------+--------+------+--------+------+------+-------------+ | 7839 | KING | 5000 | 10 | 1 | 0 | 5000 | | 7902 | FORD | 3000 | 20 | 2 | 0 | 3000 | | 7566 | JONES | 2975 | 20 | 3 | 0 | 2975 | | 9999 | BLAKE | 2850 | 10 | 4 | 0 | 2850 | | 7698 | BLAKE | 2850 | 30 | 4 | 1 | 2850 | | 7782 | CLARK | 2450 | 10 | 6 | 0 | 2450 | | 7844 | TURNER | 1500 | 30 | 7 | 0 | 1500 | | 7934 | MILLER | 1300 | 10 | 8 | 0 | 1300 | | 7654 | MARTIN | 1250 | 30 | 9 | 0 | 1250 | | 7499 | ALLEN | 1250 | 30 | 9 | 1 | 1250 | | 7876 | ADAMS | 1100 | 20 | 11 | 0 | 1100 | | 7900 | JAMES | 950 | 30 | 12 | 0 | 950 | | 7369 | SMITH | 800 | 20 | 13 | 0 | 800 | +-------+--------+------+--------+------+------+-------------+
4. row_number over(partition by deptno order by sal desc)的实现 Row_number函数返回一个唯一的值,当碰到相同数据时,排名按照记录集中记录的顺序依次递增。
select empno,
ename,
sal,
deptno,
if(@deptno = deptno, @rn := @rn + 1, @rn := 1) as rn,
@deptno := deptno
from (select empno, ename, sal, deptno
from emp e, (select @rn := 0, @deptno := '') b
order by deptno, sal desc) c;
+-------+--------+------+--------+----+-------------------+ | empno | ename | sal | deptno | rn | @deptno := deptno | +-------+--------+------+--------+----+-------------------+ | 7839 | KING | 5000 | 10 | 1 | 10 | | 7782 | CLARK | 2450 | 10 | 2 | 10 | | 7934 | MILLER | 1300 | 10 | 3 | 10 | | 7902 | FORD | 3000 | 20 | 1 | 20 | | 7788 | SCOTT | 3000 | 20 | 2 | 20 | | 7566 | JONES | 2975 | 20 | 3 | 20 | | 7876 | ADAMS | 1100 | 20 | 4 | 20 | | 7369 | SMITH | 800 | 20 | 5 | 20 | | 7698 | BLAKE | 2850 | 30 | 1 | 30 | | 7499 | ALLEN | 1600 | 30 | 2 | 30 | | 7844 | TURNER | 1500 | 30 | 3 | 30 | | 7654 | MARTIN | 1250 | 30 | 4 | 30 | | 7521 | WARD | 1250 | 30 | 5 | 30 | | 7900 | JAMES | 950 | 30 | 6 | 30 | +-------+--------+------+--------+----+-------------------+
5. max/min(sal) over(partition by deptno)的实现: (各部门最高工资) MIN (SAL)KEEP (DENSE_RANK FIRST ORDER BY DEPTNO) OVER (PARTITION BY DEPTNO) MAX (SAL)KEEP (DENSE_RANK LAST ORDER BY DEPTNO) OVER (PARTITION BY DEPTNO)
select empno,
ename,
sal,
deptno,
if(@deptno = deptno, @sal := @sal, @sal := sal) as sal_max,
@deptno := deptno
from (select empno, ename, sal, deptno
from emp e, (select @sal := 0, @deptno := '') b
order by deptno, sal desc) c;
+-------+--------+------+--------+---------+-------------------+ | empno | ename | sal | deptno | sal_max | @deptno := deptno | +-------+--------+------+--------+---------+-------------------+ | 7839 | KING | 5000 | 10 | 5000.00 | 10 | | 7782 | CLARK | 2450 | 10 | 5000.00 | 10 | | 7934 | MILLER | 1300 | 10 | 5000.00 | 10 | | 7902 | FORD | 3000 | 20 | 3000.00 | 20 | | 7788 | SCOTT | 3000 | 20 | 3000.00 | 20 | | 7566 | JONES | 2975 | 20 | 3000.00 | 20 | | 7876 | ADAMS | 1100 | 20 | 3000.00 | 20 | | 7369 | SMITH | 800 | 20 | 3000.00 | 20 | | 7698 | BLAKE | 2850 | 30 | 2850.00 | 30 | | 7499 | ALLEN | 1600 | 30 | 2850.00 | 30 | | 7844 | TURNER | 1500 | 30 | 2850.00 | 30 | | 7654 | MARTIN | 1250 | 30 | 2850.00 | 30 | | 7521 | WARD | 1250 | 30 | 2850.00 | 30 | | 7900 | JAMES | 950 | 30 | 2850.00 | 30 | +-------+--------+------+--------+---------+-------------------+
6. sum(sal) over(partition by deptno)的实现 方法 : (各部门工资汇总)
select empno,
ename,
sal,
deptno,
if(@deptno = deptno, @sal_s := @sal_s, @sal_s := sal_sum) as sal_sum,
@deptno := deptno
from (select empno,
ename,
sal,
deptno,
if(@deptno = deptno, @sal_s := @sal_s + sal, @sal_s := sal) as sal_sum,
@deptno := deptno
from (select empno, ename, sal, deptno
from emp e, (select @sal_s := 0, @deptno := '') b
order by deptno) c
order by deptno, sal_sum desc) d;
+-------+--------+------+--------+---------+-------------------+ | empno | ename | sal | deptno | sal_sum | @deptno := deptno | +-------+--------+------+--------+---------+-------------------+ | 7782 | CLARK | 2450 | 10 | 8750 | 10 | | 7839 | KING | 5000 | 10 | 8750 | 10 | | 7934 | MILLER | 1300 | 10 | 8750 | 10 | | 7369 | SMITH | 800 | 20 | 10875 | 20 | | 7566 | JONES | 2975 | 20 | 10875 | 20 | | 7788 | SCOTT | 3000 | 20 | 10875 | 20 | | 7876 | ADAMS | 1100 | 20 | 10875 | 20 | | 7902 | FORD | 3000 | 20 | 10875 | 20 | | 7499 | ALLEN | 1600 | 30 | 9400 | 30 | | 7900 | JAMES | 950 | 30 | 9400 | 30 | | 7521 | WARD | 1250 | 30 | 9400 | 30 | | 7844 | TURNER | 1500 | 30 | 9400 | 30 | | 7654 | MARTIN | 1250 | 30 | 9400 | 30 | | 7698 | BLAKE | 2850 | 30 | 9400 | 30 | +-------+--------+------+--------+---------+-------------------+
7. sum(sal) over(partition by deptno order by hiredate)的实现
select empno,
ename,
sal,
deptno,
if(@deptno = deptno, @sal_s := @sal_s + sal, @sal_s := sal) as sal_sum,
@deptno := deptno
from (select empno, ename, sal, deptno
from emp e, (select @sal_s := 0, @deptno := '') b
order by deptno, hiredate) c;
+-------+--------+------+--------+---------+-------------------+ | empno | ename | sal | deptno | sal_sum | @deptno := deptno | +-------+--------+------+--------+---------+-------------------+ | 7782 | CLARK | 2450 | 10 | 2450 | 10 | | 7839 | KING | 5000 | 10 | 7450 | 10 | | 7934 | MILLER | 1300 | 10 | 8750 | 10 | | 7369 | SMITH | 800 | 20 | 800 | 20 | | 7566 | JONES | 2975 | 20 | 3775 | 20 | | 7902 | FORD | 3000 | 20 | 6775 | 20 | | 7788 | SCOTT | 3000 | 20 | 9775 | 20 | | 7876 | ADAMS | 1100 | 20 | 10875 | 20 | | 7499 | ALLEN | 1600 | 30 | 1600 | 30 | | 7521 | WARD | 1250 | 30 | 2850 | 30 | | 7698 | BLAKE | 2850 | 30 | 5700 | 30 | | 7844 | TURNER | 1500 | 30 | 7200 | 30 | | 7654 | MARTIN | 1250 | 30 | 8450 | 30 | | 7900 | JAMES | 950 | 30 | 9400 | 30 | +-------+--------+------+--------+---------+-------------------+
sum(sal) over(partition by deptno order by hiredate)的实现 方法2:
select *
from (select e.*, @var := @var + sal as group_sum_salary
from emp e, (select @var := 0) c
order by deptno, sal) a
order by deptno, group_sum_salary;
+-------+--------+-----------+------+---------------------+---------+---------+--------+------------------+ | EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO | group_sum_salary | +-------+--------+-----------+------+---------------------+---------+---------+--------+------------------+ | 7934 | MILLER | CLERK | 7782 | 0000-00-00 00:00:00 | 1300.00 | NULL | 10 | 1300 | | 7782 | CLARK | MANAGER | 7839 | 0000-00-00 00:00:00 | 2450.00 | NULL | 10 | 3750 | | 7839 | KING | PRESIDENT | NULL | 0000-00-00 00:00:00 | 5000.00 | NULL | 10 | 8750 | | 7369 | SMITH | CLERK | 7902 | 0000-00-00 00:00:00 | 800.00 | NULL | 20 | 9550 | | 7876 | ADAMS | CLERK | 7788 | 0000-00-00 00:00:00 | 1100.00 | NULL | 20 | 10650 | | 7566 | JONES | MANAGER | 7839 | 0000-00-00 00:00:00 | 2975.00 | NULL | 20 | 13625 | | 7788 | SCOTT | ANALYST | 7566 | 0000-00-00 00:00:00 | 3000.00 | NULL | 20 | 16625 | | 7902 | FORD | ANALYST | 7566 | 0000-00-00 00:00:00 | 3000.00 | NULL | 20 | 19625 | | 7900 | JAMES | CLERK | 7698 | 0000-00-00 00:00:00 | 950.00 | NULL | 30 | 20575 | | 7654 | MARTIN | SALESMAN | 7698 | 0000-00-00 00:00:00 | 1250.00 | 1400.00 | 30 | 21825 | | 7521 | WARD | SALESMAN | 7698 | 0000-00-00 00:00:00 | 1250.00 | 500.00 | 30 | 23075 | | 7844 | TURNER | SALESMAN | 7698 | 0000-00-00 00:00:00 | 1500.00 | 0.00 | 30 | 24575 | | 7499 | ALLEN | SALESMAN | 7698 | 0000-00-00 00:00:00 | 1600.00 | 300.00 | 30 | 26175 | | 7698 | BLAKE | MANAGER | 7839 | 0000-00-00 00:00:00 | 2850.00 | NULL | 30 | 29025 | +-------+--------+-----------+------+---------------------+---------+---------+--------+------------------+
sum(sal) over(partition by deptno) 和 sum(sal) over(partition by deptno order by hiredate) 组合输出:
select e.*,
if(@deptno = e.deptno, @salary, @salary := sum_salary) as group_sum_salary,
@deptno := e.deptno
from (select e.*
from (select e.*,
if(@var = e.deptno, @sal := @sal + sal, @sal := sal) as sum_salary,
@var := e.deptno
from emp e,
(select @var := 0,
@sal := 0,
@deptno := 0,
@salary := 0) c
order by e.deptno, e.sal) e
order by e.deptno, e.sum_salary desc) e;
+-------+--------+-----------+------+------------+------+------+--------+------------+------------------+------------------+---------------------+ | EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO | sum_salary | @var := e.deptno | group_sum_salary | @deptno := e.deptno | +-------+--------+-----------+------+------------+------+------+--------+------------+------------------+------------------+---------------------+ | 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000 | NULL | 10 | 8750 | 10 | 8750 | 10 | | 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450 | NULL | 10 | 3750 | 10 | 8750 | 10 | | 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300 | NULL | 10 | 1300 | 10 | 8750 | 10 | | 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000 | NULL | 20 | 10875 | 20 | 10875 | 20 | | 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000 | NULL | 20 | 7875 | 20 | 10875 | 20 | | 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975 | NULL | 20 | 4875 | 20 | 10875 | 20 | | 7876 | ADAMS | CLERK | 7788 | 1987-05-23 | 1100 | NULL | 20 | 1900 | 20 | 10875 | 20 | | 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800 | NULL | 20 | 800 | 20 | 10875 | 20 | | 7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850 | NULL | 30 | 9400 | 30 | 9400 | 30 | | 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600 | 300 | 30 | 6550 | 30 | 9400 | 30 | | 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500 | 0 | 30 | 4950 | 30 | 9400 | 30 | | 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250 | 500 | 30 | 3450 | 30 | 9400 | 30 | | 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250 | 1400 | 30 | 2200 | 30 | 9400 | 30 | | 7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950 | NULL | 30 | 950 | 30 | 9400 | 30 | +-------+--------+-----------+------+------------+------+------+--------+------------+------------------+------------------+---------------------+
8. lag & lead (sal) over(order by hiredate)的实现
SELECT empno,
ename,
sal,
deptno,
IF(@sal is not NULL, @sal := @sal, @sal := NULL) AS ename_lag,
@sal := sal
FROM emp, (SELECT @sal := NULL) AS a
order by hiredate;
+-------+--------+------+--------+-----------+-------------+ | empno | ename | sal | deptno | ename_lag | @sal := sal | +-------+--------+------+--------+-----------+-------------+ | 7369 | SMITH | 800 | 20 | NULL | 800.00 | | 7499 | ALLEN | 1600 | 30 | 800 | 1600.00 | | 7521 | WARD | 1250 | 30 | 1600 | 1250.00 | | 7566 | JONES | 2975 | 20 | 1250 | 2975.00 | | 7698 | BLAKE | 2850 | 30 | 2975 | 2850.00 | | 7782 | CLARK | 2450 | 10 | 2850 | 2450.00 | | 7844 | TURNER | 1500 | 30 | 2450 | 1500.00 | | 7654 | MARTIN | 1250 | 30 | 1500 | 1250.00 | | 7839 | KING | 5000 | 10 | 1250 | 5000.00 | | 7902 | FORD | 3000 | 20 | 5000 | 3000.00 | | 7900 | JAMES | 950 | 30 | 3000 | 950.00 | | 7934 | MILLER | 1300 | 10 | 950 | 1300.00 | | 7788 | SCOTT | 3000 | 20 | 1300 | 3000.00 | | 7876 | ADAMS | 1100 | 20 | 3000 | 1100.00 | +-------+--------+------+--------+-----------+-------------+
select e.*, @mx, @mx := sal as LAG
from emp e, (select @mx := '') c
order by e.sal desc;
+-------+--------+-----------+------+------------+------+------+--------+---------+---------+ | EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO | @mx | LAG | +-------+--------+-----------+------+------------+------+------+--------+---------+---------+ | 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000 | NULL | 10 | | 5000.00 | | 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000 | NULL | 20 | 5000.00 | 3000.00 | | 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000 | NULL | 20 | 3000.00 | 3000.00 | | 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975 | NULL | 20 | 3000.00 | 2975.00 | | 7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850 | NULL | 30 | 2975.00 | 2850.00 | | 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450 | NULL | 10 | 2850.00 | 2450.00 | | 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600 | 300 | 30 | 2450.00 | 1600.00 | | 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500 | 0 | 30 | 1600.00 | 1500.00 | | 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300 | NULL | 10 | 1500.00 | 1300.00 | | 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250 | 1400 | 30 | 1300.00 | 1250.00 | | 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250 | 500 | 30 | 1250.00 | 1250.00 | | 7876 | ADAMS | CLERK | 7788 | 1987-05-23 | 1100 | NULL | 20 | 1250.00 | 1100.00 | | 7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950 | NULL | 30 | 1100.00 | 950.00 | | 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800 | NULL | 20 | 950.00 | 800.00 | +-------+--------+-----------+------+------------+------+------+--------+---------+---------+
select *
from (select e.*, cast(@mx as UNSIGNED) as lead, @mx := sal as var
from emp e, (select @mx := NULL) c
order by e.sal desc) c
order by c.sal;
9. RANK () OVER (PARTITION BY deptno ORDER BY sal DESC) DENSE_RANK () OVER (PARTITION BY deptno ORDER BY sal DESC) ROW_NUMBER () OVER (PARTITION BY deptno ORDER BY sal DESC)
select empno,
ename,
sal,
deptno,
if(@deptno = deptno,
if(@sal = sal, @rn := @rn, @rn3 := @rn3 + 1),
@rn := 1) as "RANK () OVER (PARTITION BY deptno ORDER BY sal DESC)",
if(@sal = sal,
@rn2 := @rn2,
if(@deptno = deptno, @rn2 := @rn2 + 1, @rn2 := 1)) as "DENSE_RANK () OVER (PARTITION BY deptno ORDER BY sal DESC)",
if(@deptno = deptno, @rn := @rn + 1, @rn := 1) as "ROW_NUMBER () OVER (PARTITION BY deptno ORDER BY sal DESC)",
@deptno := deptno,
@sal := sal
from (select empno, ename, sal, deptno
from emp a,
(select @rn := 1,
@deptno := 0,
@rn2 := 0,
@rn3 := 0,
@sal := 0,
@i := 0) b
order by deptno, sal desc) c;