数据库操作(八)

1、分页查询
Oracle分页关键字:rownum
MySql的分页关键字:limit

1)、rownum:伪列
该列在数据库表中并不存在,但是它又“存在于”
任何的表中。该字段的取值取决于查询语句的记录数。
rownum其实就是对查询出的记录数据做编号处理,
编号从1开始。

    rownum存在的sql,必须是对真实字段名的查询。

    --rownum不能直接跟*一起使用。
    select *,rownum from emp;

    --rownum正确使用
    select empno,ename,hiredate,sal,deptno,rownum
    from emp;

    --查询rownum <= 终止位置
    --查询前10条数据
    select empno,ename,hiredate,sal,deptno,rownum
    from emp
    where rownum <= 10;

    --若按每页5条数据
    --查询第一页为前5条数据:1~5
    select empno,ename,hiredate,sal,deptno,rownum
    from emp
    where rownum >= 1 and rownum <= 5;

    --查询第二页为后5条数据:6~10
    select empno,ename,hiredate,sal,deptno,rownum
    from emp
    where rownum >= 6 and rownum <= 10;

结论:在第一次进行rownum查询时,不建议使用rownum
做大于判断,否则可能达不到预期效果。
如:上面的第一页有数据,第二页无数据。

原因:rownum默认从1开始,而rownum的编号自增前提
根据条件能查询到下一条数据。查询一条数据,才会
有rownum的自增。而查询语句中where条件中要求
一上来就rownum>=6,这里有矛盾关系,
rownum从1开始,要想rownum>=6,必须使得rownum先
自增到6才行。
所以导致where rownum>=6的条件,永远都不可能满足。

解决方案:如何才能做rownum的大于操作?
先编号,再分页。

--后分页
select empno,ename,hiredate,sal,deptno,temp.num
from(
    --先编号
    select empno,ename,hiredate,sal,deptno,
            rownum num --****给rownum取别名
    from emp
) temp
where temp.num >= 6 and temp.num <= 10;

2)、分页要排序
按部门排序
因为:select ruwnum执行顺序在order by之前,
会导致查询的数据,先编号,再排序。
排序的结果比如会导致编号顺序杂乱,也仅仅是
对固定编号内的结果数据,进行小范围的排序而已。
根本也无法实现真正意义上的排序。

结论:排序一定要在编号之前完成。

最后的分页sql就得按照如下顺序:
先排序 、再编号、最后分页

--最后分页
select empno,ename,hiredate,sal,deptno,num
from(
    --再编号
    select empno,ename,hiredate,sal,deptno,
            rownum num --****给rownum去别名
    from (
    --先排序
        select * from emp order by deptno
    )
    --where rownum <= 10   --小于操作也可以此处。
)
where num >= 6 and num <= 10;--推荐使用这样编写

3)、分页参数
a、pageSize:
每页显示条数(记录数)
即一页多少条数据。

b、pageNum:
页码数
即需要查询为第几页。

举例:每页显示5条
第1页:1~5
第2页:6~10
第3页:11~15
...
第100页:496~50
对应页码的记录数为:
rownum起始位置:
(pageNum - 1) * pageSize + 1

rownum终止位置:
pageNum * pageSize;

4)、终极分页sql

    --最后分页
    select empno,ename,hiredate,sal,deptno,num
    from(
        --再编号
        select empno,ename,hiredate,sal,deptno,
                rownum num --****给rownum去别名
        from (
        --先排序
            select * from emp order by deptno
        )
    )
    where num >= ((pageNum - 1) * pageSize + 1) 
    and num <= (pageNum * pageSize);

2、高级函数
1)、decode函数
可以实现类似switch-case效果。

语法:
decode(字段名,
    search1,result1,
    search2,result2,
    ...
    searchN,resultN,  --如果没有default,逗号省略
    [default]
)

可以使用decode函数,用在两个方面:
①、分组
    统计人数
    --按照job职位分组统计人数
    select job,count(*) from emp
    group by job;

    --将MANAGER与ANALYST统计为vip组,
    --其他职位统计为other组
    --要求统计vip与other组的人数。
    select decode(job,
        'MANAGER','vip',
        'ANALYST','vip',
        'other'
    ) 职位,count(*) from emp
    group by 
    decode(job,
        'MANAGER','vip',
        'ANALYST','vip',
        'other'
    );

②、排序
    --按薪资、部门、job排序
    select * from emp
    order by job;--按职位的首字母ASIIC码自然排序

    --现实中,必须要严格遵循职位重要性来排序。
    PRESIDENT
    MANAGER
    ANALYST
    CLERK
    SALESMAN

     select * from emp
     order by 
    decode(job,
        'PRESIDENT',1,
        'MANAGER',2,
        'ANALYST',3,
        'CLERK',4,
        5
    );

2)、case-when函数
与decode效果一致,但是语法复杂很多,建议使用decode。

    语法:

        case 字段名
        when search1 then result1
        when search2 then result2
        ...
        when searchN then resultN
        else resultN+1
        end;

    --现实中,必须要严格遵循职位重要性来排序。
        PRESIDENT
        MANAGER
        ANALYST
        CLERK
        SALESMAN
         
         select * from emp
         order by 
        (case job
            when 'PRESIDENT' then 1
            when 'MANAGER' then 2
            when 'ANALYST' then 3 
            when 'CLERK' then 4
            else 5
        end);

        

    decode(字段名,
        search1,result1,
        search2,result2,
        ...
        searchN,resultN,  --如果没有default,逗号省略
        [default]
    )

3)、排序函数
查询员工信息,根据部门分组,工资顺序排序。
select * from emp
group by deptno
order by sal;
怎么办???
对于如上组内排序的sql,可以直接使用高级排序函数来实现。
根据排序结果,分为:

    ①、组内(编号)连续且唯一排序
        row_number

        语法:row_number() --连续且唯一编号
          --按以下规则
          over( 
            partition by 字段1 --按字段1分组
            order by 字段2     --按字段2排序
          )

        如:查询员工信息,根据部门分组,工资顺序排序。
        select empno,ename,hiredate,sal,deptno,
            (row_number() --连续且唯一编号
            --按以下规则
            over( 
                partition by deptno --按字段1分组
                order by sal     --按字段2排序
            )) 连续且唯一
        from emp;

    ②、组内(编号)连续不唯一排序
        dense_rank
        语法:dense_rank() --连续不唯一编号
          --按以下规则
          over( 
            partition by 字段1 --按字段1分组
            order by 字段2     --按字段2排序
          )

        如:查询员工信息,根据部门分组,工资顺序排序。
        select empno,ename,hiredate,sal,deptno,
            (dense_rank() --连续不唯一编号
            --按以下规则
            over( 
                partition by deptno --按字段1分组
                order by sal     --按字段2排序
            )) 连续不唯一编号
        from emp;
    

    ③、组内(编号)不连续不唯一排序
        rank
        语法:rank() --不连续不唯一编号
          --按以下规则
          over( 
            partition by 字段1 --按字段1分组
            order by 字段2     --按字段2排序
          )

        如:查询员工信息,根据部门分组,工资顺序排序。
        select empno,ename,hiredate,sal,deptno,
            (rank() --不连续不唯一编号
            --按以下规则
            over( 
                partition by deptno --按字段1分组
                order by sal     --按字段2排序
            )) 不连续不唯一编号
        from emp;

        

2、高级函数
1)、分支函数
decode
分支效果。
来实现排序、分组。

case-when与decode函数功能相同

2)、排序函数
row_number():组内连续且唯一。
rank():组内不连续不唯一。
dense_rank():组内连续不唯一。

正课:
1、高级函数
1)、分支函数
2)、排序函数
3)、集合操作

    ①、并集
        union:自动去重联合查询
        --得到15条数据
        select * from emp -- 员工表集合 15
        union
        select * from leader;--领导表集合 6
        
        union all:不去重联合查询
        --得到21条数据
        select * from emp -- 员工表集合 15
        union all
        select * from leader;--领导表集合 6

    ②、交集
        intersect
        --得到6条数据
        select * from emp -- 员工表集合 15
        intersect
        select * from leader;--领导表集合 6

    ③、差集
        minus
        集合1 差 集合2
            --得到9条数据
        select * from emp --员工表集合 15
        minus
        select * from leader;--领导表集合 6
    
        集合2 差 集合1
        --得到0条数据
        select * from leader--领导表集合 6
        minus
        select * from emp;--员工表集合 15

你可能感兴趣的:(数据库操作(八))