美文网首页
oracle查询重复记录的第一条

oracle查询重复记录的第一条

作者: wsj1211 | 来源:发表于2020-08-10 15:40 被阅读0次

    查询重复记录的第一条

    select a.*
    from
    (select bat22.*,
           row_number() over(partition by MAT12ID, MAT12NAME order by bat22id desc) rn
    from bat22) a
    where a.rn=1;
    

    rn代表行号 总是获取行号为1的数据

    group by是分组函数,partition by是分区函数(像sum()等是聚合函数),注意区分。
    ``
    先对cno 中相同的进行分区,在cno 中相同的情况下对degree 进行排序

    oracle 利用 decode extract,add_months 查询六个月内公司员工考勤

    
    select D.userId,D.month,SUM(D.clockInNum)AS clockInNum,sum(D.clockOutNum)as clockOutNum,SUM(D.NUMS)AS total,D.nickName,D.deptName,D.userType from (
    SELECT
    ia.user_id as userId ,
        EXTRACT(MONTH FROM add_months( SYSDATE, -10 )) AS month,
        SUM(DECODE( EXTRACT( MONTH FROM ia.ATTENDANCE_DATE ), EXTRACT( MONTH FROM add_months( SYSDATE, -10 )), 1, 0 )) AS nums,
        SUM(DECODE( EXTRACT( MONTH FROM ia.ATTENDANCE_DATE ), EXTRACT( MONTH FROM add_months( SYSDATE, -10 )), decode(sdd.DICT_LABEL,'请假', 1, '矿工', 1, 0), 0 )) AS clockOutNum,
    SUM(DECODE( EXTRACT( MONTH FROM ia.ATTENDANCE_DATE ), EXTRACT( MONTH FROM add_months( SYSDATE, -10 )), decode(sdd.DICT_LABEL,'外出', 1, '出差', 1, '正常', 1,'迟到', 1,'早退', 1, 0), 0 )) AS clockInNum,
    su.nick_name AS nickName,
        sd.dept_name AS deptName,
        ia.user_type AS userType 
    FROM
        in_attendance ia
        LEFT JOIN sys_user su ON su.user_id = ia.user_id
        LEFT JOIN sys_dept sd ON sd.dept_id = su.dept_id
        LEFT JOIN SYS_DICT_DATA sdd ON sdd.dict_code = ia.ATTENDANCE_STATUS 
    WHERE
        ia.del_flag = 0 
    GROUP BY
        su.nick_name,sd.dept_name,ia.user_type,sdd.DICT_LABEL,ia.user_id
        )D
        GROUP BY D.nickName,D.deptName,D.userType,D.month,D.userId
    

    多条数据合并为一条

    select sys.stragg(a.isdropout) isdropout from yhb a where a.times=1;
    逗号分隔
    select trim(both ',' from sys.stragg(to_char(a.isdropout)||NVL2(a.isdropout, ',', ''))) as isdropout from yhb a where a.times=1;

    select 获取时间差

    ceil((To_date(a.END_TIME , 'yyyy-mm-dd hh24-mi-ss') - To_date(a.START_TIME, 'yyyy-mm-dd hh24-mi-ss'))) as hours,

    查询树状结构 (这块直接粘贴的 https://blog.csdn.net/zxysshgood/article/details/81671836?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.channel_param

    ) 感谢 作者
    这几天看sql看到了有关connect by和level的关键字用法,以前都用mysql也没用过这个关键字,感觉挺有用的,就学了下,整理一下学习过程。

      **首先,connect by和level都是为了快速的查询层级关系的关键字,在代理关系中,或者权限关系中,经常会有层层嵌套的场景,比如,同行数据的第一个字段是ID,第二个字段是parentID,parentID表示他的上级ID是谁。**
    
    1. 如一条数据,ID为1,parentID为0,表示没有上级,即顶层,grade 为老板

    2. 第二条数据,ID为2,parentID为1,表示上级为1,grade 为总监

    3. 第三条数据,ID为3,parentID为2,表示上级为2,grade 为经理

      这就是一个三级的层级关系事例。
      

      在这种情况下,如果想知道某个:比如 一级代理的所有二级代理和三级代理的有关行是谁,就很麻烦了。如果使用mysql数据库,就有两种方法

    MYSQL

    ** 第一种是在java代码或者别的service层,或工具层中编写有关层级关系解析的方法代码,然后把解析的数据放在redis或者map中(如果不放在redis 或者map中,数据量大的时候,每次调用关系都要重新算一遍是很大的消耗)。**

    ** 第二种是在mysql数据库中编写相对的存储过程,在select 查询的时候调用自己封装好的方法,获取相应的数据库信息。**

    但是oracle 中,则很贴心的提供了对应的方法来解决上述的问题,这就是关键字:***connect by ***

    *** 其实简单来说,其基本语法是***

    ** select …,level from tablename**

    ** start with 条件1
    connect by prior 父字段id=子字段id
    where 条件3;**

    ** 例子:**

    ** SELECT a.FUNCID,a.PARENTID,LEVEL FROM AUTH_FUNC a START WITH a.FUNCID=3173
    CONNECT BY PRIOR a.FUNCID = a.PARENTID;**

    ** 以上述模板为例,LEVEL是查询的层级,START WITH a.FUNCID=3173,表示从该条件开始寻找层级关系,CONNECT BY PRIOR a.FUNCID=a.PARENTID 代表,优先按照a.FUNCID当做基础,该例中(PARENTID的值,绑定的是FUNCID),所以查找FUNCID=3173的所有儿子孙子,及其层级(儿子LEVEL是2,孙子LEVEL是3)**

    ** 如果变成CONNECT BY a.FUNCID= PRIOR a.PARENTID,则代表起始为a.FUNCID=3173,优先按照PARENTID查找,即寻找FUNCID=3173这条数据的所有父节点行**

    ** 这里有点难以理解,但是其实就是如果,PRIOR 放在父字段端,就是寻找STRAT WITH 标注节点的所有的子节点,如果PRIOR 放在子字段端,就是寻找STRAT WITH 标注节点的所有的父节点**

    ** 因为一个儿子只有一个父亲,而一个父亲可能有多个儿子,所以当PRIOR放在父字段端的时候,可能有多个层级族,因为在找儿子。当放在子字段端的时候,最多只会有一个层级族,因为,他在找爸爸。**

    关于 connect by 和level 还有startwith 的详细介绍和延伸,我在学习过程中,找到了两个很好的博客,在此就不转载了,直接转网址了,以供以后自己学习和看此篇博客的人学习。

       oracle connect by用法篇:[https://blog.csdn.net/wang_yunj/article/details/51040029/](https://blog.csdn.net/wang_yunj/article/details/51040029/)
    
       Oracle中start with...connect by子句的用法:[http://www.blogjava.net/xzclog/archive/2010/03/05/314642.html](http://www.blogjava.net/xzclog/archive/2010/03/05/314642.html)
    
        看完这两篇博客,应该是能懂很多东西的,我这里在尝试和学习的过程中,也做了一些事例,如果在有oracle数据库,且想很快形象的学习有关这块知识,也可以直接在oracle中执行我的事例代码,配上注释,应该能简单不少。
    

    # oracle-按月、日、时分组查询数据,为空的数据补零

    ------月

    
    `select` `nvl(t1.tvalue, 0) ``"data1"``, t2.datevalue ``"name"`
    
    `from` `(``select` `sum``(t.TSAI03) tvalue, TO_CHAR(t.TSAI01, ``'yyyy-mm'``) timevalue`
    
    `from` `TSA009 t`
    
    `where` `TO_CHAR(t.TSAI01, ``'YYYY-MM-DD'``) ``like` `'2012%'`
    
    `and` `t.unit_code ``like` `'411500A0050000'`
    
    `group` `by` `TO_CHAR(t.TSAI01, ``'yyyy-mm'``)) t1,`
    
    `(``select` `'2012-'` `|| lpad(``level``, 2, 0) datevalue`
    
    `from` `dual`
    
    `connect` `by` `level` `< 13) t2`
    
    `where` `t1.timevalue(+) = t2.datevalue`
    
    `order` `by` `t2.datevalue`
    
     |
    
    -----日
    
    | 
    
    `select` `nvl(t1.tvalue, 0)` `"data1"``, t2.datevalue` `"name"`
    
    `from` `(``select` `sum``(t.TSAI03) tvalue,`
    
    `TO_CHAR(t.TSAI01,` `'yyyy-mm-dd'``) timevalue`
    
    `from` `TSA009 t`
    
    `where` `TO_CHAR(t.TSAI01,` `'YYYY-MM-DD'``)` `like` `'2012-04%'`
    
    `and` `t.unit_code` `like` `'411500A0050000'`
    
    `group` `by` `TO_CHAR(t.TSAI01,` `'yyyy-mm-dd'``)) t1,`
    
    `(``select` `'2012-04-'` `|| lpad(``level``, 2, 0) datevalue`
    
    `from` `dual`
    
    `connect` `by` `level` `< (``select` `to_number(substr(last_day(to_date(``'2012-04-10'``,`
    
    `'yyyy-mm-dd'``)),`
    
    `0,`
    
    `2))`
    
    `from` `dual) + 1) t2`
    
    `where` `t1.timevalue(+) = t2.datevalue`
    
    `order` `by` `t2.datevalue`
    
     |
    
    ----时
    
    | 
    
    `select` `nvl(t1.tvalue, 0)` `"data1"``, t2.datevalue` `"name"`
    
    `from` `(``select` `sum``(t.TSAJ03) tvalue,`
    
    `TO_CHAR(t.TSAJ01,` `'yyyy-mm-dd hh24'``) timevalue`
    
    `from` `TSA010 t`
    
    `where` `TO_CHAR(t.TSAJ01,` `'YYYY-MM-DD'``)` `like` `'2012-04-10%'`
    
    `and` `t.unit_code` `like` `'411500A0050000'`
    
    `group` `by` `TO_CHAR(t.TSAJ01,` `'yyyy-mm-dd hh24'``)) t1,`
    
    `(``select` `'2012-04-10 '` `|| lpad(``level``, 2, 0) datevalue`
    
    `from` `dual`
    
    `connect` `by` `level` `< 25) t2`
    
    `where` `t1.timevalue(+) = t2.datevalue`
    
    `order` `by` `t2.datevalue`
    
    

    # oracle 中(+)是什么意思

    原文内容:
    oracle中的(+)是一种特殊的用法,(+)表示外连接,并且总是放在非主表的一方。

    例如

    左外连接:select A.a,B.a from A LEFT JOIN B ON A.b=B.b;

    等价于select A.a,B.a from A,B where A.b = B.b(+);

    再举个例子,这次是右外连接:select A.a,B.a from A RIGHT JOIN B ON A.b=B.b;

    等价于select A.a,B.a from A,B where A.b (+) = B.b;

    个人补充:

    数据表的连接有:
    1、内连接(自然连接): 只有两个表相匹配的行才能在结果集中出现
    2、[外连接]: 包括
    (1)左外连接
    (2)右外连接
    (3)全外连接(左右两表都不加限制)
    3、[自连接]连接发生在一张基表内)

    有 (+) 的一方代表有可以为空,即副表

    oracle中的(+)是一种特殊的用法,(+)表示外连接,并且总是放在非主表的一方。例如左外连接:select A.a,B.a from A LEFT JOIN B [ON] A.b=B.b;等价于select A.a,B.a from A,B where A.b = B.b(+);再举个例子,这次是右外连接:

    select A.a,B.a from A RIGHT JOIN B  on A.b=B.b;
    等价于
    select A.a,B.a from A,B where A.b (+) = B.b;
    

    # Decode与NVL和NVL2区别

    Decode

    decode(条件,值1,翻译值1,值2,翻译值2,...,缺省值) 该函数与程序中的 If...else if...else 意义一样

    NVL

    格式:NVL( string1, replace_with)

    功能:如果string1为NULL,则NVL函数返回replace_with的值,否则返回string1的值,如果两个参数都为NULL ,则返回NULL。

    注意事项:string1和replace_with必须为同一数据类型,除非显式的使用TO_CHAR函数进行类型转换。

    select nvl(sum(t.dwxhl),1) from tb_jhde t 就表示如果sum(t.dwxhl) = NULL 就返回 1

    Oracle在NVL函数的功能上扩展,提供了NVL2函数

    NVL2

    **nvl2 **(E1, E2, E3) 的功能为:如果E1为NULL,则函数返回E3,否则返回E2

    结合Decode 和 NVL等函数 常常结合使用,例如

    select monthid,decode(nvl(sale,6000),6000,'NG','OK') from output

    扩展知识

    sign()函数根据某个值是0、正数还是负数,分别返回0、1、-1,

    如果取较小值就是
    select monthid,decode(sign(sale-6000),-1,sale,6000) from output,即达到取较小值的目的。

    相关文章

      网友评论

          本文标题:oracle查询重复记录的第一条

          本文链接:https://www.haomeiwen.com/subject/zbuxkktx.html