关于SQL的一些知识点

一、先将数据库的日期显示设定为显示全部信息,再实验使用日期函数的情况:

先通过alter session的方式对数据库的日期显示格式进行设置:

 

开始试验所有的日期函数:

1.trunc函数:

 

可以得到trunc函数可以对日期截取到以分为单位,但是trunc函数无法对秒级的日期进行操作;

2last_day函数

 

显然,last_day函数会以天为单位得到当月最后一天的日期,不会对时分秒进行处理;

3.next_day函数:


同样,next_day函数可以求出以当前日期为准,下个星期的某一天是几月几号,但是,依然不会对时分秒进行操作;

4.add_months函数:

 

以sysdate为例,可以看出add_months函数同样不会对数据进行时分秒级的处理,并且,对于add_months需要注意的一点是,此函数并不是简单的将日期加30天,而是加1个月,如下:


由以上结果可知,

1.      Add_months函数中第二个参数为1,就是增加1个月,参数为-1,则减少1个月;

2.      使用add_months函数时增加的是月份而不是天数,如1月9日增加1个月是2月9日,但是1月31日增加1个月是2月28日(2018年是非闰年,2月只有28天),而不是3月2日。

3.      使用add_months函数时,如果当前的日期已经超过了下个月的最大日期,则只会返回下个月最后一天,如:1月30日和1月31日都超过了28,但是使用函数后,只增加到了2月28日。

4.      在add_months函数第二个参数为负值时,如果当前的日期超过了上个月的最后一天,则会返回上个月最后一天的日期,如3月31日和3月30日的日期都超过了28,但是使用函数后,依然返回了2月28日,通过次实验更能看出,add_months函数增加和减少的是月份而不是天数;

5.      在add_months函数第二个参数为负值时,如果当前月的最后一天比上个月的最后一天小,会返回上个月的最后一天,如:2月份最后一天是28日,在使用了add_months函数后,结果返回了1月31日;

通过以上结论,可以知道,add_months函数在执行时,是以月为单位的,而不是以天为单位的;

5.round函数:

 

由实验结果可知,round函数对日期进行操作时:和trunc函数一样,无法对秒级的数据进行操作,但是round函数在进行舍入操作时和正常的情况有一点不同:

1.      对年进行舍入操作时,以月份的6舍7入为标准;

2.      对月份进行舍入操作时,以日的15舍16入为标准(2月份依然通用)

3.      对日进行舍入操作时,以周一至周三,周四至周日进行取舍;


当前日期时1月24日是周三,由于采用周一至周三舍去的原则,函数使用后返回的当前的周一;

4.      对时、分进行舍入操作时,都是按照下一级以30为分界点,大于30就入,小于30就舍去的规则执行;

二、A、B两张完全相同的表,按照A表为B表插入数据

如果表中有主键约束,由于主键约束非空且唯一,所以这种情况比较简单(假设主键列是id)

Insert into b

SELECT * FROM aWHERE id NOT IN (SELECT id FROM b);

将A表和B表的id列进行比较,若A表ID列中有B表没有的值,则将A表中的数据插入到B表中。

由于表中ID列有主键约束,所以他们的ID列的值是非空且唯一的,通过将B表中的ID列和A表中的ID列进行对比,为B表插入数据。

由于谓词in的参数允许有多个,所以可以将B表id列全部查询出来,与A表的id列进行比较。

Where关键字后可以得到true、false、unknown三个值(unknown先不讨论),只有where得到true,SELECT语句才会输出数据,在谓词in前加上not关键字,即对比较出来的结果进行否定,所以当比较出结果为false,则where语句返回true,此行才会被SELECT语句选中并输出。

如果没有主键约束,有两种方法可实现

1.      insert into B

SELECT * FROM aWHERE id not in (select id from b where id is not null);

2.      insert into B

SELECT * FROM a where not exists(select * from b wherea.id=b.id);

第一种方法,此时表中没有主键列,所以对id列进行比较时,需要处理列中的null值,但是对表中的重复值不进行处理。

第二种方法, exists是一种只能得到true或false的谓词,它的参数一般是关联子查询,它的判断方式是关联子查询是否能查询出数据,若能查询到记录则返回真,若不能查询到记录则返回假。

在谓词前加not关键字,对谓词得到的结果进行否定运算,若子查询查到数据,虽然谓词得到真值,但是进行否定运算后,整个where子句得到false,所以SELECT语句不输出此记录。

对没有的主键约束的情况进行演示:

 

通过两种方法插入数据:

第一种方法:


第二种方法:


通过演示可以得到:

1.  谓词in语法简单容易掌握,但是对null值的处理比较劣势;

2.  谓词exists语法比较难理解,但是可以对null值进行有效的处理;

三、按照A表修改B表

有两张表现在有两个表A B

A       ID NAME

         1 a

         2 b

         3 c

        33 d

        44 e

         7 f

        99 g

B       IDNAME

         1 a

        22 b

        33 d

        44 e

           c

         7 f

 

要求根据B表ID列对A表进行修改,如果B是空值则A不动

         这里面有个需要注意的地方,由于A表中name列有g,如果根据全表进行修改,会在B表上产生null值。

1.      update A

set ID=(SELECT idFROM b WHERE a.name=b.name)

where exists(select* from b where a.name = b.name and id is not null);

通过谓词exists对修改的数据进行范围限定,并且当表B中id列有null值时,不对表A进行修改;

2.      如果B表没有重复行时可以

Update A

Set id = (selectid from b where a.name=b.name)

Where name in (selectname from b);

由于B表中没有重复行,所以可以直接用谓词in对修改范围进行限定。

演示:


根据B表修改A表:



将结果进行对比可以看出,如果不对范围进行限定,会将A表中的c行和g行同时更新成null值,就和要求不符合,所以必须对范围进行限定; 

四、删除表test中重复的行

1.先将重复的行找出来

Select * from testwhere (a,b) in (select a,b from test group by a,b having count(*)>1);

通过group by子句和having子句,用count函数确认出拥有重复行的数据。若count(*)>1则说明这一行数据有重复值。

2.通过delete语句将重复数据删除

 Deletefrom test

Where (a,b) in (selecta,b from test group by a,b having count(*)>1);                  

但是,这样会删除所有的行,如果想留下一行,需要再加入条件

Deletefrom test

Where(a,b) in (select a,b from test group by a,b having count(*)>1)

Androwid not in (select min(rowid) from test group by a,b having count(*)>1);

 演示:


对此表进行删除重复行操作


首先通过查询语句对重复行进行查询


通过这种方法虽然可以删除重复行,但是会删除所有的行,这不符合我们的要求,所以,对词语句进行加工:


通过rowid伪列将重复行中,rowid最小的那一列不进行删除操作,就能得到我们想要的数据了。

删除前后对比:



五、在dual表中输出1000行数据;

 Dual表是一张只有1行1列的表,用普通的select查询时无法查出1000行数据的,所以,要用到level伪列:level伪列是Oracle自带的一种伪列,使用方法:

Selectlevel from dual connect by level<=1000;

由于1000行数据无法全部显示,我使用count函数将查询出的结果进行了一次统计;


我们可以看到,用这种就可以在dual表中输出1000行数据了;但是level伪列还有一些需要注意的地方,他不能直接通过where子句设定条件,而是通过connect by进行条件设定;

六、通过A表得到B表:

A表:

B表:


结果演示:


这种方法使用了group by语句和三个字符函数,但是由于group by对ID列进行分组并对数据行进行排序时是无规则排序的,导致在wm_concat函数中,字符也是无规则组合的,所以无法得到我们想要的结果。然后我使用了另一种方法对其进行查询:

 

此时由于字符的排序是在关联子查询中进行的,不受ID列的影响,得到了我们想要的结果;

数据库函数的一些用法:

1.      通过使用 substr函数和length函数截取某一列中除了首字母以外所有的字符:

Select substr(a,2,length(a))from test;

结果:


通过length函数将字符串的长度读取出来,并作为substr函数的参数应用,将字符串除了首字母以外的所有字符串提取出来。

并且通过这个实验可以知道,将函数进行嵌套使用,函数的执行顺序是从内到外;

2.      trunc函数的特殊用法

    1.      查询某个月第一天:

        Select trunc(日期,mm) fromdual;

    2.      查询某个季度第一天

        Select trunc(日期,q) fromdual;

         结果:



在第一个特殊用法中,我先使用了数据类型转换函数,将数字类型的20171010转换成日期类型,然后通过trunc函数和参数’mm’对日期进行操作,得到了当月的第一天;

在第二个特殊用法中,参数’q’对函数进行操作,得到了本季度的第一天,Oracle从一月份开把全年12个月以每三个月为一季度进行划分,所以得到的数据是2017年10月1日;

Dual表是Oracle中的一张特殊的表,它只有一行一列,他本身没有任何数据,只是为了Oracle数据库的完整性创造出来的一张表;

3.Wm_concat列转行函数:     

Selectwm_concat(列名) from 表;就可以将一张表中的某一列以行的形式显示出来


原表中的数据是以列的形式存储,通过函数就可以转换为行显示,通常此函数和replace函数一起用


只使用wm_concat函数,每一行数据之间是用‘,’隔开的,通过replace函数就可以将’,’转换成’|’。

4.列转行函数pivot;把某张表的两列通过函数合并成一行进行输出:

select * from test

pivot(sum(b) for a in('behavior','bride','custom','exotic','groom','offensive','tradition'));

 

注意:使用此函数时,pivot(列1 for 列2)中,列1必须使用函数,否则会报错,并且进行查询的表中只能包含pivot函数中出现的列;


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值