**
sql基础知识(笔记)(一)
**
当时学习sql的笔记 (oracle)
1.简单查询:
select * from 表名;
其中select和from是关键字,泛绿色,Oracle所有泛绿色的都是关键字
*是通配符,代表所有的列;
表名即需要查询的表的名字,我们要看哪张表里的数据,就写哪个表的名字,查出来的就是这个表的所有数据;
每一句SQL后都需要有分号,分号代表一个SQL语句的结束,切记.
select 列1,列2,列3 from 表名;
当我们要查询表中的一部分列时,就不能使用了,因为查出的是所有的列,比如成绩单表,语文老师只想看语文成绩,就不需要使用select *
当我们想查询部分列时,把想查询的列名代替*即可,如果要查询多列,则多个列名之间用逗号隔开.
比如查询emp表的empno和ename,按照我们上面说的,就可以写作 select empno, ename from emp;更多的列也是如此,都好隔开即可.
这里注意一个细节,我们查询的列名的顺序,决定结果中列展示的前后顺序,即先查询了empno,则数据展示时先展示empno,再查询了ename,则ename第二位展示.
查询结果的展示顺序,只与查询顺序有关.select *时顺序一直是固定的,因为表中列的顺序是固定的,DBA_TAB_COLUMNS表中有COLUMN_ID这个东西,它就决定了表中列的顺序,也决定了展示顺序;
表取别名和列取别名
select b.列1,b.列2 from 表名 b;
我们在查询一部分列时,实际都是列名前都是有表名的,即 表名.列名 的形式,取别名后,就可以用别名代替表名,即变为 别名.列名形式. 因为只有一张表,所有 表名. 这个部分可以省略。
但我们之后会学习到从多张表查询数据,这时候就不能省略了.尤其表名比较长的时候,表取别名就很实用了,可以提高我们的编码效率,不用再多次数据表名.
select 列1 as 别名1, 列2 别名2 from 表名;
列取别名时,需要注意别名的命名规范:
尽量是单词缩写,若多个单词时,用下划线_连接,不能使用中划线;
数字,_开头时,需要用双引号包裹
列名中包含特殊符号,比如括号等时,需要用双引号包裹
别名可以是中文,且不需要引号,这也是唯一的一处.
**
2.筛选查询:
**
数据类型:
数据类型是指的是数据的格式,这里的数据不是单指数字,是说表里的内容.
常见数据类型有如下几个:
varchar2:字符串类型,包含各种字符,字母,汉字,符号等等.因为编码格式的不同,汉字所占位数会有所差异,GBK 汉字占2位,UTF-8占3位
varchar2区别于varchar,回忆区别的点在哪儿:都是存放字符类型 varchar2是可变的,varchar2(40),如果我只存放了1个字母,实际占位1 varchar分配多少占多少, varchar(40),存放了一个字母,这40个字符全部占满,别人无法使用
字符串格式使用时需要用单引号包裹.(有没有例外情况?) 最大长度 4000
number:数字类型,即数据.1,2,3等的这种.数字是可以直接比较大小的. number(5) 代表是数字类型,最大长度5位. number(4,2)代表最大长度4位,其中小数2位.
比如number(5),最大长度5位,数据可以是1位,比如数字7,也可以是3位,比如156,最多不超过5位.
number(4,2):是指最大长度4位,其中小数2位.即数据可以是1,但显示为1.00,因为有2位小数.即整数最多2位,小数一直是2位.
最长38位
date:时间类型,代表时间,比如当前时间 sysdate. to_date(), to_char()
筛选查询:
之前讲解的都是查询整张表的全部内容或者某几列的全部内容,如果要查询一部分数据,就得用到筛选查询.
基本语法:
select * from 表名 where 列名=值;--查询表中列名的值=值的数据.
比如select * from emp where ename='ADAM';--查询emp表中ename是'ADAM'的人的信息
看列数据类型的几种方式:
1.select * from 表名;
鼠标放在某一列数据上,下方会显示这一列数据的类型;
2.Ctrl+鼠标左键,在表名上,点击进去后可以看到每一列的数据类型;
3.USER_TAB_COLUMNS视图内,有每一列的数据类型长度等信息,COLUMN_ID也在里面
其中表名后出现一个关键字 where,可以理解为条件是,或者满足条件,后面跟上查询的条件 列名=值. 表达的意思是满足列中的数据等于后面的值这个条件.
这里面不止=一个运算符,另外还有>,<,>=,<=,<>, between… and, in, not in
其中注意between … and是包含边界的,所有在使用时要注意,如果是统计数据,则慎用.
当前我们是只有一个查询条件,实际应用中我们经常是多个条件同时使用,提高查询的准确度.这里需要引入and和or满足多个条件查询.
and:意为同时满足and前后两个条件
or:满足or前后任意一个条件即可,也可以理解为查询结果是满足前面条件的结果和满足后面条件结果的合集.
而且and和or有优先级关系: ()>and>or
即当有and和or同时存在时,先执行and,再执行or. 如果有括号,则先执行括号. 回看笔记,看一下我们之前的练习题.
日常编码中,我们需要使用括号,提高代码可读性.
筛选查询中还有两个点:
- in的用法: 现阶段in可以理解为多个or的组合,在某个范围之内的数据 同理还有 not in
- oracle判空: is null,判断不为空时 is not null.其余的方式都不对(=‘ ’, = null)等.
练习题:
create table emp_0204
(emp_no number(4),
emp_name varchar2(50),
emp_job varchar2(50),
emp_hiredate date,
emp_dept varchar2(50)
);
insert into emp_0204 values(0001,'Sucre','MANAGER',to_date('19850308','YYYYMMDD'),'10');
insert into emp_0204 values(0002,'Alex','SALESMAN',to_date('19820110','YYYYMMDD'),'10');
insert into emp_0204 values(0003,'Bill','SALESMAN',to_date('19950820','YYYYMMDD'),'10');
insert into emp_0204 values(0004,'Shown','SALESMAN',to_date('19871102','YYYYMMDD'),'10');
insert into emp_0204 values(0005,'Han','SALESMAN',to_date('19931008','YYYYMMDD'),'10');
insert into emp_0204 values(0006,'George','MANAGER',to_date('19981126','YYYYMMDD'),'20');
insert into emp_0204 values(0007,'John','SALESMAN',to_date('19830510','YYYYMMDD'),'20');
insert into emp_0204 values(0008,'Peter','SALESMAN',to_date('19930815','YYYYMMDD'),'20');
insert into emp_0204 values(0009,'Matthew','SALESMAN',to_date('19940619','YYYYMMDD'),'20');
insert into emp_0204 values(0010,'Edward','PRESIDENT',to_date('20081028','YYYYMMDD'),'30');
insert into emp_0204 values(0011,'Hamilton','SALESMAN',to_date('20010609','YYYYMMDD'),'30');
insert into emp_0204 values(0012,'Connor','SALESMAN',to_date('19821112','YYYYMMDD'),'30');
commit;
1.查询所有MANAGER的入职时间;
select emp_hiredate from emp where job='MANAGER';
2.查询所有SALESMAN的名字;
select emp_name from emp where emp_job='SALESMAN';
3.查询部门20的MANAGER;
select * from emp where emp_job='MANAGER' and emp_dept='20';
4.查询入职时间在90年之后且职位不是SALESMAN的;
select *from emp where emp_hiredate>to_date('19900101','YYYYMMDD') and emp_job <>'SALESMAN';
5.查询部门10的MANAGER和部门20的SALESMAN;
select * from emp where
(emp_dept='10' and emp_job='MANAGER')
or
(emp_dept='20' and emp_job='SALESMAN');
6.查询部门30的PRESEDENT和部门20的MANAGER;
select * from emp where
(emp_dept='30' and emp_job='PRESIDENT')
or
(emp_dept='20' and emp_job='MANAGER');
7.查询所有部门的SALESMAN;
select * from emp where emp_job='SALESMAN';
8.查询部门10的所有SALESMAN;
select * from emp where emp_dept='10' and emp_job='SALESMAN';
**
模糊查询
**
模糊查询的概念:条件不完整或者不充分的时候,需要用到模糊查询
like的用法,模糊查询的语法: select * from 表名 where 列名 like ‘%内容%’;
%和_的含义:%在它和它之前有0个或者多个字符 _在当前位置有一个字符
select * from emp where ename like '%TH%';--ename中包含TH字样的
select * from emp where ename like '___TH';--查询ename以TH结尾,且长度是5位的
搜索以固定内容开头或者结尾的数据
select * from 表名 where 列名 like '内容%';--以固定内容开头
selct * from 表名 where 列名 like '%内容';--以固定内容结尾的数据
搜索固定长度的数据
select * from 表名 where 列名 like '_____';--搜索长度是5位的数据 考虑函数方式
搜索带%或者_的数据
select * from 表名 where 列名 like '%/%%' escape '/';
select * from 表名 where 列名 like '%/_%' escape '/';
搜索带%和_且不挨着的数据
'%/%%_/_%' escape '/'
'%/_%_/%%' escape '/'
排序
排序语法:
select * from 表名 order by 列名 ;
排序方式;
order by:排序,也是关键字,按照之后的列和排序方式进行排序
排序的两种方式 asc,desc:升序 asc (默认), 降序 desc
多种排序的语法和样式: order by 列名1 asc, 列名2 desc;–先按照第一列排序,当第一列中有重复数据时,按照第二列排序.如果第一列中没有重复数据,则根据第一列的排序就是最终结果
select * from 表名 order by 列名1 desc, 列名2 asc;
order by 1, order by 2: 1,2代表查询内容的第几列.
排序使用的位置
模糊查询与排序联用时如何使用
select * from 表名 where 列名 Like ‘%内容%’ order by 列名 排序方式;
练习:
insert into emp_0204 values (13,'AB_CD','TEST',sysdate-20,'10');
insert into emp_0204 values (14,'A%D','TEST',sysdate-100,'20');
insert into emp_0204 values (15,'A%D_E%F','TEST',sysdate-15,'30');
insert into emp_0204 values (16,'AD_E%F','TEST',sysdate-15,'30');
commit;
--1.查询emp_0204表emp_name包含n的所有人信息;
select * from emp_0204 where emp_name like '%n%';
--2.查询emp_0204表emp_name以H开头的;
select * from emp_0204 where emp_name like 'H%';
--3.查询emp_0204表emp_name以F结尾的;
select * from emp_0204 where emp_name like '%F';
--4.查询emp_0204表emp_name中包含_的;
select * from emp_0204 where emp_name like '%/_%' escape '/';
--5.查询emp_0204表emp_name中包含%的;
select * from emp_0204 where emp_name like '%/%%' escape '/';
--6.查询emp_0204表emp_name中包含%和_的;
select * from emp_0204 where emp_name like '%/_%' escape '/' and emp_name like '%/%%' escape '/';
select * from emp_0204 where emp_name like '%/_%/%%' escape '/' or emp_name like '%/%%/_%' escape '/';
--7.查询emp_0204中emp_dept为10的员工信息,以emp_name升序展示;
select * from emp_0204 where emp_dept='10' order by emp_name asc;
--8.查询emp_0204中emp_dept为20的员工信息,按照emp_job降序展示;
select * from emp_0204 where emp_dept='20' order by emp_job desc;
--9.查询emp_0204中emp_dept为30的员工信息,先按照emp_job升序展示,再按照emp_name降序展示;
select * freom emp_0204 where emp_dept='30' order by emp_job asc,emp_name desc;
--10.查询emp_0204中emp_dept为20的员工信息,按照emp_hiredate降序展示,再按照emp_name升序展示;
select *from emp_0204 where emp_dept='20' order by emp_hiredate desc, emp_name asc;
--11.查询emp_0204中emp_name包含e字母的,按照emp_name升序排序;
select * from emp_0204 where emp_name like '%e%' order by emp_name asc;
**
分组:
**
基本语法 多列分组(语法和含义)
group by 列名1,列名2;
select之后的内容(聚合函数,每个什么意思 coount(1), count(2))
分组列,聚合函数处理过的列
MAX–最大值
MIN–最小值
SUM–求和
AVG–平均数
COUNT–数量 count(*), count(1), count(2),
count(列名) 如果列中有空值,那么得出的数量是不包括空值的.
select 内容 from 表名 group by 列名;
内容:分组列或者聚合函数处理过的列
having和where:
where:针对全表数据做过滤
having:针对分组内的数据过滤
group by 列名 having 内容;
having之后的内容:
1.分组列可用;
2.聚合函数可以用;
group by, having, order by的写的时候的顺序
SQL执行顺序
select * from 表名 where 条件 group by 列 having 内容 order by 列 asc/desc;
1.同时使用group by, having和order by时的写法;
2.执行顺序:
(1):where条件;
(2):group by;
(3):having 过滤;
(4):select;
(5):order by;
case when 2种写法
case 列名
when 值1 then 执行语句1
when 值2 then 执行语句2
when 值3 then 执行语句3
else 执行语句4 end case;
case
when 列>值1 then 执行语句1
when 列>值2 and 列<值3 then 执行语句2
when 列>值4 and 列<值5 then 执行语句3
else 执行语句4 end case;
扩展:
利用group by过滤重复数据
1:distinct
2:group by–max(rowid)/min(rowid) group by的列名是分组列,通常是主键列
3:union
4:row_number() over(partition by)
rowid–每一行数据都有一个rowid,是一个唯一的字符串,跟数据一一对应,可以用来过滤重复数据
rownum–伪劣,可以过滤数据的前几行,rownum<4,但是不能rownum>某个数据.
习题:
--针对emp_0204表:
--1.获取10部门最晚的入职时间;
select max(emp_hiredate) from emp_0204 where emp_dept='10';
--2.获取20部门的最早入职时间;
select min(emp_hiredate) from emp_0204 where emp_dept='20';
--3.获取SALESMAN中最早的入职时间;
select min(emp_hiredate) from emp_0204 where emp_job='SALESMAN';
--4.获取所有MANAGER中入职最晚的;
select max(emp_hiredate) from emp_0204 where emp_job='MANAGER';
--5.筛选人数超过6人的部门;
select emp_dept from emp_0204 group by emp_dept having count(1)>6
--7.查询sal<1000, 1000-3000,3000-5000和>5000的各阶段人数;
select SUM(case when
sal is null then 1 else 0 end) sal_null,
SUM(case when sal<1000 then 1 else 0 end) sal_1000,
sum(case when sal>=1000 and sal<3000 then 1 else 0 end) sal_1000_3000,
sum(case when sal>=3000 and sal<=5000 then 1 else 0 end) sal_3000_5000,
sum(case when sal>5000 then 1 else 0 end) sal_5000
from emp_0204;