oracle查询重复记录的第一条

查询重复记录的第一条

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查询重复记录的第一条)