数据库笔记02:查询与统计数据

/***************************
 第二单元:查询与统计数据
***************************/

/*

SELECT [DISTINCT][TOP n [PERCENT]] *|字段列表|表达式列表|函数列表
FROM 数据表(单表或多表)
WHERE 查询条件
ORDER BY 字段1 DESC,....,字段n DESC

难点在于正确书写查询条件。

简单条件,用到关系运算符:=、!=、>、<、>=、<=

针对字符型数据,有一个用户模糊查询的运算符:LIKE(%、_)

复杂条件,用到逻辑运算符来连接关系表达式:NOT-->AND-->OR

NOT: Complement 补集
AND: Intersection 交集 ∩
OR: Union 并集

有两个特殊的运算符:BETWEEN...AND...、IN

*/

/* 任务:查找Class表里系部号为01的记录。*/

SELECT *
FROM Class
WHERE DepartNo='01';


/* 任务:查找Student表里所有姓张的学生记录。*/

SELECT *
FROM Student
WHERE StuName LIKE '张%';


/* 任务:查找Student表里姓张单名的学生记录。*/

SELECT *
FROM Student
WHERE StuName LIKE '张_';


/* 任务:查找Student表里ClassNo为20000001所有姓张的学生记录。*/

SELECT *
FROM Student
WHERE StuName LIKE '张%' AND ClassNo='20000001';


/* 任务:查找Student表里ClassNo为20000004所有姓张和姓李的学生记录。*/

错误的处理方式:


正确的处理方式:

SELECT *
FROM Student
WHERE (StuName LIKE '李%' OR StuName LIKE '张%') AND ClassNo='20000004';    


/* 练习:查询Course表里课程编号不为004,005,007的课程信息,包含课程编号与课程名字段 */

SELECT CouNo 课程编号,CouName 课程名
FROM Course
WHERE CouNo!='004' AND CouNo!='005' AND CouNo!='007';


SELECT CouNo 课程编号,CouName 课程名
FROM Course
WHERE NOT (CouNo='004' OR CouNo='005' OR CouNo='007');


SELECT CouNo 课程编号,CouName 课程名
FROM Course
WHERE CouNo NOT IN('004','005','007');


还有没有别的处理方式?


课堂练习:查询课程编号在004与007之间的课程,包含课程编号和课程名称,字段名显示为中文。



交换004和007的位置,看看结果怎样?

结论:BETWEEN min_value AND max_value

/**********************************
统计查询,要用到五个聚合函数:
SUM()、AVG()、COUNT()、MAX()、MIN()
聚合函数的用法请大家参看教材P48
***********************************/

关于统计,有几种情况:
1、总体统计
2、总体条件统计(WHERE)
3、分组统计(GROUP)
4、分组统计有总体条件(WHERE-GROUP)
5、分组条件统计(GROUP-HAVING)
6、总体条件与分组条件统计(WHERE-GROUP-HAVING)


/* 任务:统计Course表中有多少门选修课 */

SELECT COUNT(*) 课程门数
FROM Course;


课堂练习:统计课程编号大于007的课程门数。

/* 任务:统计Student表里班级编号为20000004的学生人数 */

SELECT COUNT(*) 学生人数
FROM Student
WHERE ClassNo='20000004';

/* 任务:统计每个班级的学生人数。*/

/* 分析:要按班级编号来进行分组汇总,就要用到GROUP BY字句来实现 */

SELECT ClassNo 班级编号,COUNT(*) 学生人数
FROM Student
GROUP BY ClassNo;

/* 任务:统计全部课程的限选人数之和 */

SELECT SUM(LimitNum) 限选人数总和
FROM Course;

/* 任务:统计信息技术类课程的限选人数之和 */

SELECT SUM(LimitNum) 限选人数总和
FROM Course
WHERE Kind='信息技术';

/* 任务:查看所有类别课程的限选人数之和 */

SELECT Kind 课程类别,SUM(LimitNum) 限选人数总和
FROM Course
GROUP BY Kind;

/* 任务:查询Course表,了解各门课程受欢迎的程度。*/

应该选择WillNum而不是ChooseNum作为统计字段,要理解为什么。

SELECT MAX(WillNum) 最大报名人数,MIN(WillNum) 最小报名人数,AVG(WillNum) 平均报名人数
FROM Course;

/* 问题:如何才能让平均报名人数显示为整数? */

SELECT MAX(WillNum) 最大报名人数,MIN(WillNum) 最小报名人数,CAST(AVG(WillNum) AS INT) 平均报名人数
FROM Course
/* 任务:查询最受欢迎的课程名称以及报名人数 */

/* 分析:筛选报名人数等于最大报名人数的课程,而最大报名人数是前一个查询的结果,
         一个查询的结果作为另一个查询条件的组成部分,这就是嵌套查询 */

SELECT CouName 课程名称,WillNum 报名人数
FROM Course
WHERE WillNum=(SELECT MAX(WillNum) FROM Course); /* 子查询 */


/* 任务:查询最受不欢迎的课程名称以及报名人数 */

SELECT CouName 课程名称,WillNum 报名人数
FROM Course
WHERE WillNum=(SELECT MIN(WillNum) FROM Course); /* 子查询 */


/* 任务:查询最受欢迎和最不受欢迎的课程名称及报名人数 */

/* 方法一 */
SELECT CouName 课程名称,WillNum 报名人数
FROM Course
WHERE WillNum=(SELECT MAX(WillNum) FROM Course) 
      OR WillNum=(SELECT MIN(WillNum) FROM Course);


/* 方法二 */
DECLARE @Max_Num AS INT, @Min_Num AS INT
SELECT @Max_Num=MAX(WillNum),@Min_Num=MIN(WillNum)
FROM Course
SELECT CouName 课程名称,WillNum 报名人数
FROM Course
WHERE WillNum IN (@Max_Num,@Min_Num)
GO


/***********************************************

分组查询:GROUP BY, ALL, CUBE, COMPUTE, COMPUTE BY, HAVING

具体用法,请大家参看教材P50

************************************************/

/* 任务:按课程类别分组统计课程门数,并给出总门数。*/

SELECT Kind 课程类别,COUNT(*) 课程门数

FROM Course
GROUP BY Kind WITH CUBE;

/* 任务:统计报名人数超过15人的各类课程的最多报名人数与最少报名人数。 */

/* 总体筛选条件,针对所有记录的,通过WHERE字句来实现 */

SELECT Kind 课程类别,MAX(WillNum) 最多报名人数,MIN(WillNum) 最少报名人数
FROM Course
WHERE WillNum>15  /* 总体筛选条件 */
GROUP BY Kind;

/* 任务:查询报名人数超过15人并且平均报名人数超过30人的课程类别与平均报名人数 */

/*
  总体筛选条件:报名人数超过15人,通过WHERE字句来实现
  组内筛选条件:平均报名人数超过30人,通过HAVING字句来实现  
*/

SELECT Kind 课程类别,CAST(AVG(WillNum) AS INT) 平均报名人数
FROM Course
WHERE WillNum>15  /* 总体筛选条件 */
GROUP BY Kind
HAVING AVG(WillNum)>30; /* 组内筛选条件 */

/* 任务:查询课程类别为“信息技术”与“管理”的平均报名人数,显示课程类别 */

SELECT Kind 课程类别,CAST(AVG(WillNum) AS INT) 平均报名人数
FROM Course
WHERE Kind IN ('信息技术','管理')
GROUP BY Kind;

SELECT Kind 课程类别,CAST(AVG(WillNum) AS INT) 平均报名人数
FROM Course
WHERE Kind IN ('信息技术','管理')
GROUP BY ALL Kind;

/* 任务:查看Course表中系部编号为02的课程信息,显示该系部的平均报名人数以及总数 */

SELECT *
FROM Course
WHERE DepartNo='02'
COMPUTE AVG(WillNum),SUM(WillNum);

/* 任务:按系部分组查看课程信息,并显示每个系部的平均报名人数及总数 */

SELECT *
FROM Course
ORDER BY DepartNo  /* 一定要按分组计算的字段排序 */
COMPUTE AVG(WillNum),SUM(WillNum) BY DepartNo;

说明:在SQL Server 2012中,COMPUTE已被废弃。


/************************************************************

子查询(嵌套查询):一个查询的结果作为另外一个查询条件的组成部分

查询条件可以使用关系运算(六种)、BETWEEN...AND...、IN、EXISTS

专门讲一下EXISTS函数。EXISTS(子查询),如果子查询结果不为空,返回真,否则返回假

****************************************************************/

/* 任务:查询报名人数超过平均报名人数的课程信息 */

SELECT *
FROM Course
WHERE WillNum>(SELECT AVG(WillNum) FROM Course);

/* 任务:显示平均报名人数大于30的系部开设的课程信息 */

SELECT *
FROM Course
WHERE DepartNo IN (SELECT DepartNo
                   FROM Course
                   GROUP BY DepartNo
                   HAVING AVG(WillNum)>30);

/* 任务:查询已经报名选修课程的学生信息,只显示学号与姓名 */

SELECT StuNo 学号,StuName 姓名
FROM Student
WHERE EXISTS(SELECT StuNo
             FROM StuCou
             WHERE StuNo=Student.StuNo AND State='报名');

大家思考一下,可不可以用关联查询来完成?

关联查询有两种实现方式:(1)利用where子句实现关联;(2)利用join关键字实现关联
看有重复记录,需要采用DISTINCT关键字来去重。


/*********************************
利用UNION关键字联合查询结果
——相当于集合的并集运算
**********************************/

/*任务:将系部表(DepartNo, DepartName)与班级表(ClassN0, ClassName)的内容联合起来显示 */

SELECT DepartNo, DepartName
FROM Department
UNION
SELECT ClassNo, ClassName
FROM Class

/************************************
关联查询:基于多张表的查询
有两种实现关联的方式:
1、通过WHERE字句实现关联
2、通过关键字JOIN实现关联
*************************************/

/* 任务:查询学生的学号、姓名以及所在的班级号码和班级名称 */

/* 分析:班级表与学生表是一对多的关系,有公共字段ClassNo*/ 

/* 方法一、通过WHERE字句实现关联 */

SELECT Student.StuNo 学号, Student.StuName 姓名, Student.ClassNo 班级号码, Class.ClassName 班级名称
FROM Class, Student
WHERE Class.ClassNo=Student.ClassNo;

/* WHERE字句具有双重功能:不仅可用于设置筛选条件,也可用于设置关联条件 */

/* 方法二、利用关键字JOIN来实现关联 */

SELECT Student.StuNo 学号, Student.StuName 姓名, Student.ClassNo 班级号码, Class.ClassName 班级名称
FROM Class INNER JOIN Student ON Class.ClassNo=Student.ClassNo;

/* 任务:查询“韩霞”同学选修课程情况,只显示姓名与课程名称两个字段 */

/*
       分析:查询结果的两个字段分别来自Student表与Course表,但是这两张表没有公共字段,
                      因此两个表无法直接关联,多对多的关系是无法直接关联起来的,怎么办呢?
                      那么我们就要找到另外一张表作为桥梁让这两张表关联起来。打开数据库关系图,
                      dbo.Diagram_0,可以看到Student表与Course表是通过StuCou表间接关联起来的。
                      于是,这个任务的完成就涉及到了三表的关联查询。
         
                      Student与StuCou表的公共字段是StuNo(学号),关联条件:Student.StuNo=StuCou.StuN0
                      StuCou与Course表的公共字段是CouNo(课程编号),关联条件:StuCou.CouNo=Course.CouNo
*/

/* 方法一、通过WHERE字句实现三表关联 */

SELECT StuName 姓名, CouName 课程名称
FROM Student, StuCou, Course
WHERE Student.StuNo=StuCou.StuNo AND StuCou.CouNo=Course.CouNo /* 关联条件 */
                 AND StuName='韩霞';  /*  筛选条件 */

/* 方法二、通过关键字JOIN实现三表关联 */

SELECT StuName 姓名, CouName 课程名称
FROM Student INNER JOIN StuCou ON Student.StuNo=StuCou.StuNo  /* 关联与关联条件 */
             INNER JOIN Course ON  StuCou.CouNo=Course.CouNo   /* 关联与关联条件 */          
WHERE StuName='韩霞';
                 
SELECT StuName 姓名, CouName 课程名称
FROM Student INNER JOIN StuCou INNER JOIN Course   /* 三表关联 */             
             ON  StuCou.CouNo=Course.CouNo ON Student.StuNo=StuCou.StuNo    /* 关联条件 */          
WHERE StuName='韩霞';
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

酒城译痴无心剑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值