SQL语句之语法汇总(二)

时间:2022-09-16 14:39:57

 

      继前一篇介绍SQL的简单语法后,本片将主要介绍实际应用中常用的语法,如数据排序order by、通配符Like过滤、空值处理、数据分组group by、限制结果集行数top 5*、子查询、去掉数据重复distinct、联合结果集union/union all、数字函数、字符串函数、日期函数、类型转换函数cast /convert、索引、表连接join等,其中会结合具体代码及例子予以说明。(考虑文章长度,部分内容将放大汇总三)

  为方便查看示例select语句,文章最后会附上需要创建的table表:  

一.数据分组group by(聚合函数)

  1.1代码:

1.group by简单语句
--统计每个年龄段的人数
1). select FAge,count(*)as 人数 from T_Employee group by FAge;   --right
2). select FAge,FSalary,count(*) from T_Employee group by FAge;   --error
--程序报错:选择列表中的列 'T_Employee.FSalary' 无效,因为该列没有包含在聚合函数或 GROUP BY 子句中。
--分析:按照age分组,同一个age可能有好几个工资水平,计算机无法确定显示哪个而报错!
3). select FAge,max(FSalary)as 最高工资,count(*) as 人数 from T_Employee group by FAge; --right!
--分析:显示出age每组的最高工资即可
2.group by与where、having1). select FAge,count(*) from T_Employee where count(*)>1 group by FAge;--error:  
2). select FAge,count(*) from T_Employee group by FAge having count(*)>1   --right:

 

------------------------------------------------

  博主经营一家发饰淘宝店,都是纯手工制作哦,开业冲钻,只为信誉!需要的亲们可以光顾一下!谢谢大家的支持!
店名:
  小鱼尼莫手工饰品店
经营:
  发饰、头花、发夹、耳环等(手工制作)
网店:
  http://shop117066935.taobao.com/

  ---------------------------------------------------------------------

继续正题... 

  

 

 1.2分析:

  1)group by是按照某一个字段来对table中信息进行整合分组,在代码"group by简单语句"中,1、3正确,而2错误,可以做如下分析:

  我们以FAge进行分组,即将每个年龄段的信息进行整合,获取到的结果可能是23岁的有abc三个人,工资为100、200、300,那么只能取其中某一个工资水平显示,如

max(FSalary),而不能直接写FSalary,否则计算机必然无法确定显示哪个而报错!参考下图,为“3)”的显示结果:

SQL语句之语法汇总(二)

  2)聚合语句不能出现在 WHERE 子句中,除非有having ,因而语句"1)"错误,而语句"2)"出现having,正确,分析:having对获取到的每组信息,再进行过滤,取得人数超过1的组(结果显示:25岁 3人等)
  3)既然存在上述情况,那是不是having可以取代where语句呢?答案是否定的,参考代码:
a). select FAge, count(*) from T_Employee where FSalary>2000 group by FAge;   --right
b). select FAge, count(*) from T_Employee group by FAge having FSalary>2000;  --error:  
c). select FAge, count(*) from T_Employee group by FAge having FAge>25;       --right
  分析:"a)"中使用where,可以实现对分组前的数据进行过滤;即如果25岁组中有3人(3000,2000,4000),那么使用where语句后,结果为25 2人。
  而having只能对获得的组信息进行过滤,即对"select FAge, count(*) from T_Employee group by FAge"的结果进行过滤,此时无法再对FSalary去筛选,无法实现where实现的功能,因而"b)"错误;
  但如果对年龄刷选having FAge>25就正确,因为select结果中包含FAge字段,可以进行简单where对年龄的筛选,即"c)"正确!  

二.数据排序

  2.1代码:  

1). 单字段排序:
select * from T_Employee order by FAge ASC;         --对年龄进行排序
2). 多字段排序
select * from T_Employee order by FAge ASC ,Fsalary ASC; --进一步排序(年龄相同的,按照工资排序)!前面的优先级高!
3). 对过滤后结果进行排序:
select * from T_Employee where FAge>24 order by FAge DESC;

  2.2 分析

  1)排序条件可以有多个,但越前优先级越高;

  2)ASC升序(default)、 DESC降序,平时使用排序时,ASC方式虽为默认,但最好不要省略,增强代码可读性

三.通配符

   3.1代码

1). 通配符_,单个字符:
select * from T_Employee where FName LIKE '_erry';
2). 通配符%,零或多个字符:
select * from T_Employee where FName like '%n%';      --FName中含有字母n的
select * from T_Employee where FNumber like 'DEV%';   --FNumber中以DEV开始的

  3.2分析

  注意区分Like中 单字符  不定字符用法的区别!

四. 空值处理

  4.1代码:

1)空值查询
select 'abc'+'123'     --结果:abc123
select ''+'123'        --结果:123
select null+'123'      --结果:NULL
select * from T_Employee where FName=null;        --error  没有结果,可以尝试<null  >null <>null均无结果!
select * from T_Employee where FName is null;     --right  查询到name为null的结果!
select * from T_Employee where FName is not null; --error  查询到所有name不为null的结果! 
2)空值的处理
update T_Employee set FSubCompany=null,FDepartment='Sales'where FNumber='SALE004';  --设定某项为null
select isnull(FSubCompany,'未知子公司') from T_Employee                   --字段为null的则显示默认值'未知子公司'
4.2分析:
  1)数据库中,一个列如果没有指定值,那么值就是null,此处的null与c#中的null不同,数据库中表示“不知道”,而不是“没有”
  2)可以尝试FName!=null、FName=<null、FName=>null、FName=<>null均无结果!
五.限制结果集的行数

  5.1 代码:

1). select top 5* from T_Employee                --显示表中前五个
2). select top 5* from T_Employee order by FSalary Desc  --按照工资倒序排列,取前五个(最高的五个) 

  5.2 分析

  top 5* 表示表中前五条信息,由升序或降序来决定顺序。

  top 5 FSarray表示工资的前五个,由升序或降序来决定顺序。

六.子查询

  6.1代码: 

select top 5* from T_Employee
where FNumber not in (select top 5 FNumber from T_Employee order by FSalary Desc)
order by FSalary Desc;

  6.2 分析

  select语句嵌套,实现子查询,即在"select得到的表"中进行二次查询! 

 select top 5 FNumber from T_Employee order by FSalary Desc得到前五个数字;在此条件再用where查询!
七. 去掉数据重复distinct
  7.1代码
1). select FDepartment from T_Employee;                    --会有重复,完全显示查询结果
2). select distinct FDepartment from T_Employee;       --没有重复
3).
select FDepartment,FSubCompany from T_Employee;        --会有重复,完全显示查询结果
4).
select distinct FDepartment,FSubCompany from T_Employee;   --仅消除完全重复的行!

  7.2 分析

  参考,当table为下表时  

  SQL语句之语法汇总(二)

执行"1)",完全显示出table的所有FDepartment 内容,字段会有重复,如红线标注区域;
执行"2)",显示FDepartment所有分类,没有重复 
执行"3)",完全显示出table的所有FDepartment,FSubCompany 内容,会有重复,完全显示查询结果
执行"4)",仅消除完全重复的行。当FDepartment,FSubCompany数据完全相同时,数据合并,如的二个红色框中,会合并成一条数据,而第一个框中数据有差异不会合并,

八. union与union all
  8.1代码:
1). union会将重复数据合并9+6->14条!"表1中5条数据"+"表2中6条数据",结果可能小于11,因为将重复的FName字段合并
select FName from TempEmployee  !
union
select FName from T_Employee;
2). union all不考虑重复数据,完全合并5+6->11条!!
select FName from TempEmployee  
union all
select FName from T_Employee;
3).其他关于union的示例(只要对应字段类型一致(不严谨)即可)
select FName,FAge from TempEmployee
union
select FName,FAge from T_Employee;

select FName,FAge ,0 from TempEmployee
union
select FName,FAge ,1 from T_Employee;

select FName,FAge ,FIdCardNumber from TempEmployee
union
select FName,FAge,FsubCompany from T_Employee;
--可用字段'临时工,无部门'补齐,实现union操作
select FIdCardNumber,FName,FAge ,'临时工,无部门' fromTempEmployee   
union 
select FNumber,FName,FAge,FDepartment from T_Employee;
4).错误: 
select FName,FAge ,0 from TempEmployee --"0和FDepartment "类型不能转换 union select FName,FAge,FDepartment from T_Employee;

  8.2分析

  1)union合并会消除重复项,而union  all不考虑重复,会将数据完全合并累加

  2) union时,需要两个table中要union的结果集中,具有相同的列数,且列类型要相容才可以union

  3)union需要进行重复值扫描,效率比较低,所以如果不是确定要进行重复行合并,那么就使用union all

  4)例子

    a.在T_Employee中,(报表)查询员工最低年龄、最高年龄?参考:  

select '正式员工最高年龄', max(FAge) from T_Employee
union all
select '正式员工最低年龄', min(FAge) from T_Employee
union all
select '临时工最高年龄', max(FAge) from TempEmployee
union all
select '临时工最低年龄', min(FAge) from TempEmployee;

    b.查询正式工信息:工号、工资,在最后一行加上员工工资额合计,参考:

select FNumber,FSalary from T_Employee
union 
select '员工工资合计:',sum(FSalary) from T_Employee

 


 (待续...)

 

附:创建的几个table

Table  T_Employee
--创建表

drop table T_Employee
create table T_Employee(FNumber varchar(20),FName varchar(20),FAge int,FSalary numeric(10,2),PRIMARY KEY(FNumber));
insert into T_Employee(FNumber,FName,FAge,FSalary)values('DEV001','Tom',25,8300);
insert into T_Employee(FNumber,FName,FAge,FSalary)values('DEV002','Jerry',28,4300);
insert into T_Employee(FNumber,FName,FAge,FSalary)values('HR001','Jane',25,5300);
insert into T_Employee(FNumber,FName,FAge,FSalary)values('HR002','Tina',26,6000);
insert into T_Employee(FNumber,FName,FAge,FSalary)values('IT001','Smith',23,3300);
insert into T_Employee(FNumber,FName,FAge,FSalary)values('IT002','Tom',27,9300);
insert into T_Employee(FNumber,FName,FAge,FSalary)values('SALE001','John',24,3300);
insert into T_Employee(FNumber,FName,FAge,FSalary)values('SALE002','Kerry',22,5500);
insert into T_Employee(FNumber,FName,FAge,FSalary)values('SALE003','Stone',25,4500);
insert into T_Employee(FNumber,FName,FAge,FSalary)values('SALE004','john',23,5500);


--修改表:

alter table T_Employee add FSubCompany varchar(20); --分公司
alter table T_Employee add FDepartment varchar(20); --部门
alter table T_Employee add FInDate datetime; --入职日期
update T_Employee set FInDate='2010-09-07 12:00:00', FSubCompany='Beijing',FDepartment='development'where FNumber='DEV001';
update T_Employee set FInDate='2011-09-07 12:00:00', FSubCompany='Shenzhen',FDepartment='development'where FNumber='DEV002';
update T_Employee set FInDate='2012-09-07 12:00:00', FSubCompany='Beijing',FDepartment='HumanResource'where FNumber='HR001';
update T_Employee set FInDate='2009-09-07 12:00:00', FSubCompany='Beijing',FDepartment='HumanResource'where FNumber='HR002';
update T_Employee set FInDate='2010-09-07 12:00:00', FSubCompany='Shenzhen',FDepartment='InfoTech'where FNumber='IT001';
update T_Employee set FInDate='2011-09-07 12:00:00', FSubCompany='Beijing',FDepartment='InfoTech'where FNumber='IT002';
update T_Employee set FInDate='2011-09-07 12:00:00', FSubCompany='Beijing',FDepartment='Sales'where FNumber='SALE001';
update T_Employee set FInDate='2012-09-07 12:00:00', FSubCompany='Shenzhen',FDepartment='Sales'where FNumber='SALE002';
update T_Employee set FInDate='2009-09-07 12:00:00', FSubCompany='Beijing',FDepartment='Sales'where FNumber='SALE003';
update T_Employee set FInDate='2009-09-07 12:00:00', FSubCompany='Shenzhen',FDepartment='Sales'where FNumber='SALE004';

 

--创建Table TempEmployee

create table TempEmployee(FIdCardNumber varchar(20),FName varchar(20),FAge int not null);

insert into TempEmployee(FIdCardNumber,FName,FAge)values('12345601','张',20);

insert into TempEmployee(FIdCardNumber,FName,FAge)values('12345602','Tom',24);

insert into TempEmployee(FIdCardNumber,FName,FAge)values('12345603','李',18);

insert into TempEmployee(FIdCardNumber,FName,FAge)values('12345604','孙',26);

insert into TempEmployee(FIdCardNumber,FName,FAge)values('12345605','周',30);

insert into TempEmployee(FIdCardNumber,FName,FAge)values('12345606','武',27); 

 

店名:
  小鱼尼莫手工饰品店
经营:
  发饰、头花、发夹、耳环等(手工制作)
网店:
  http://shop117066935.taobao.com/