第七章高级数据库查询

Posted shaoyayu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第七章高级数据库查询相关的知识,希望对你有一定的参考价值。

第七章、高级数据库查询

内容提要:

1. 掌握一般数据查询功能扩展

2. 掌握查询的并、交、差运算

3.掌握子查询的使用

4.了解其他一些查询功能

第一节 一般数据查询功能扩展

1.1. SELECT语句

//SQL的一般查询语句
SELECT [DISTINCT] [TOP n] select_list 
//将查询的结果插入到了一个表中
[INTO new_table]  
//需要查询的表
[FROM table_source]
//查询的条件
[WHERE search_conditition]
//对查询的结果进行分组
[GROUP BY group_by_expression]
//指定组或聚合函数的查找条件
[HAVING search_condition]
//对查询的结果进行排序
[ORDER BY order_expression [ASC|DESC]]
//对查询结果结果后面生成汇总数据行
[COMPUTE expression] 

1.2.使用TOP限制结果集

TOP n [percent][WITH TIES]

? Top n 前n行

? Top n [percent]前n%行

? [WITH TIES]:包括最后一行取值并列的结果。

例题:

【例1】查询单价最高的前三种商品的商品名、商品类别和单价,包括并列情况。

SELECT TOP 3 WITH TIES GoodsName, GoodsClassName,SaleUnitPrice,FORM Table_Goods a JOIN Table_GoodsClass b
ON a.GoodsClassID=b.GoodsClassID ORDER BY SaleUnitPrice DESC

1.3.使用CASE函数

  • 分情况显示不同类型的数据。CASE函数是一种多分支表达式。

  • 两种类型:

  1. 简单CASE函数
  2. 搜索CASE函数

语法:

CASE
 WHEN 布尔表达式1 then 结果表达式1
 WHEN 布尔表达式2 then 结果表达式2
 ……
 WHEN 布尔表达式n then 结果表达式n
 [ELSE 结果表达式n+1]
END

案例:

分析下列语句的作用(P110)

SELECT a.GoodsID,商品销售类别=CASE 
WHEN COUNT(b.GoodsID)>10 THEN ‘热门商品’
WHEN COUNT(b.GoodsID)BETWEEN 5 AND 10 THEN ‘一般商品’
WHEN COUNT(b.GoodsID)BETWEEN 1 AND 4 THEN ‘难销商品’
ELSE ‘滞销商品’
END
FROM Table_Goods a LEFT JOIN Table_SaleBillDetail b
ON a.GoodsID=b.GoodsID GROUP BY a.GoodsID

1.4.将查询结果保存到新表中

SELECT 查询列表序列 INTO <新表名>

FROM 数据源……(其他行过滤、分组语句)

注意:表名前加#为局部临时表,##为全局临时表,只有表名为永久表。

临时表只能当前查询可用

例子:SELECT * INTO #HD_Customer FROM Table_Customer WHERE ……

第二节 查询结果的并、交、差运算

2.1.并运算

  • 并运算(UNION):将多个查询结果合并为一个结果集。。

  • 语法:

SELECT 语句1
    UNION [ALL]
SELECT 语句2
    UNION [ALL]
 ……

使用UNION注意:

  • 要进行合并的查询,SELECT中列数必须相同,语义相同。

  • 每个相对应列的数据类型隐式兼容,如char(20)与varchar(40)。

  • 合并后结果采用第一个SELECT语句的列标题。

  • 若需排序,则GROUP BY语句写在最后一个SELECT之后,且排序的语句是第一个SELECT中的列名。

2.2.交运算

  • 交运算:返回同时在两个集合中出现的记录。

  • 语法:

SELECT 语句1
    INTERSECT 
SELECT 语句2
    INTERSECT ……
SELECT 语句n

2.3.差运算

  • 差运算:返回第一个集合中有而第二个集合中没有的的记录。

  • 语法:

SELECT 语句1
EXCEPT 
SELECT 语句2
EXCEPT……
SELECT 语句n

第三节 相关子查询

  • 子查询是一条包含在另一条SELECT语句里的SELECT语句。外层的SELECT语句叫外层查询,内层的SELECT语句叫内层查询(或子查询)。

  • 子查询总是写在圆括号中。

包括子查询的SELECT语句主要采用以下格式中的一种:

(1) WHERE expression [NOT] IN (subquery)

(2) WHERE expression comparison_operator [ANY | ALL]

(3)WHERE [NOT] EXISTS (subquery)

案例:

1、

使用子查询进行基于集合的测试

查询和王晓同地区的人,除了王晓以外

SELECT Cname,Address 
FROM Table_Customer
WHERE Address   IN(
    SELECT Address 
    FROM Table_Customer  
    WHERE Cname=‘王晓’)
AND Cname!= ‘王晓’

2、

使用子查询进行比较测试

查询单价最高的商品的名称和单价

SELECT Goodname,SaleUnitPrice 
FROM Table_Goods a 
WHERE SaleUnitPrice=
(
    SELECT MAX(SaleUnitPrice) 
    FROM Table_Goods
)

3、

使用子查询进行存在性测试

查询购买了单价高于2000元商品额顾客的会员卡号。

SELECT DISTINCT CardID 
FROM Table_SaleBill 
WHERE EXISTS(
    SELECT * 
    FROM Table_SaleBillDetail 
    WHERE SaleBillID=Table_SaleBill.SaleBillID 
    AND UnitPrice>2000
)

第四节 其他形式的子查询

4.1.替代表达式的子查询

  在SELECT的选择列表中嵌入了一个只返回一个标量值的子查询。

实例:

SELECT Cname,Address,(
    SELECT COUNT(*) 
    FROM Table_Customer b ON a.CardID=b. CardID 
    WHERE CustomerID=‘C001’
)AS TotalTimes 
FROM Table_Custmer 
Where CustomerID=‘C001’

4.2.派生表

  • 也称为内联视图,是将子查询作为一个表处理,产生的新表为“派生表”。

实例:

查询至少买了G001和G002两种商品的顾客号和顾客名。

SELECT CustomerID,CName 
FROM (
    SELECT * 
    FROM Table_SaleBill a  JOIN Table_SaleBillDetail b 
    ON  a.SaleBillID=b. SaleBillID 
    WHERE  GoodsID=‘G001’
) AS T1 JOIN (
    SELECT * 
    FROM Table_SaleBill a                           
    JOIN Table_SaleBillDetail b ON  a.SaleBillID=b. SaleBillID 
    WHERE   GoodsID=‘G002’
) AS T2
ON T1.CardID=T2.CardID
JOIN Table_Customer c ON c.CardID=T1. CardID

第五节 其他一些查询功能

5.1.开窗函数

  • 在SQL Server 中,一组行被称为一个窗口。

  • 与聚合函数一样,开窗函数也是对行集组进行聚合计算,但是它不像普通聚合函数那样每组只返回一个值,开窗函数可以为每组返回多个值,因为开窗函数所执行聚合计算的行集组是窗口。

  • 与聚合函数不同的是,开窗函数在聚合函数后增加了一个OVER 关键字。

  • 开窗函数的调用格式为:
    函数名(列)OVER(选项)
    • OVER 关键字:表示把函数当成开窗函数而不是聚合函数。
    • SQL 标准允许将所有聚合函数用做开窗函数,使用OVER 关键字来区分这两种用法。

实例1:

将OVER字句与聚合函数结合使用

  设有课程表Course(Cno,CName,Credit,Semester)查询全部课程的Cno,CName,Semester, Credit信息及其该学期开设课程的总、最高、平均、最低Credit 。

SELECT Cno,CName,Semester ,Credit
SUM(Credit) OVER(PARTITION BY Semester) AS ‘Total’,
AVG(Credit) OVER(PARTITION BY Semester) AS ‘Avg’,
MIN(Credit) OVER(PARTITION BY Semester) AS ‘Min’,
MAX(Credit) OVER(PARTITION BY Semester) AS ‘Max’,
FROM Course

实例2:

将OVER子句与排名函数一起使用

  • 排名函数RANK()
RANK() OVER([<partition_by_clause>,…[n]]<order_by_clause>)
  • 注意: 排名函数具有不确定性 。

? 排名从1开始,不一定是连续整数。

SELECT OrderID, ProductID, OrderQty 
    RANK() OVER(PARTITION BY OrderID ORDER  BY  OrderQty DESC ) 
    AS RANK
FROM OrderDetail
ORDER  BY OrderID 

其他排名函数

  • DENSE_RANK()

排名是连续整数

  • NTILE()

将有序分区中的行划分到指定数目的组中,编号从1开始,函数返回此行所属的组的编号。

  • ROW_NUMBER()

返回结果集中每个分区内的序列号,每个分区的第一行从1开始。

5.2.公用表表达式

  • 公用表表达式(CommonTableExpression,CTE):

将查询结果集指定一个临时名字,这些命名的结果集就是公用表表达式。

  • 格式:
WITH <common_table_expression>[,…n]
<common_table_expression>::=
Expression_name[(column_name [,…n])]
AS
(SELECT语句)

实例 :

定义一个统计每个会员购买商品总次数的CTE,并利用CTE查询会员卡号和购买商品的次数。

定义:

WITH BuyCount(CardID,Counts)
AS(SELECT CardID,Count(*) 
   FROM Table_SaleBill 
   GROUP BY CardID 
  )

使用:

AS(
    SELECT CardID,Counts 
    FROM BuyCount 
    ORDER BY Counts
)

例题:

1、

1.设某数据库中有旅客表A(旅客编号,城市)和旅客表B(旅客编号,城市),现将所有旅客的数据存储这两张表中。请补全如下查询语句,使得该查询语句能查询所有旅客所在的全部的不重复的城市。
SELECT 城市 FROM 旅客表A
(  )
SELECT 城市 FROM 旅客表B
答案: UNION

2、

2.设有购买表(顾客号,商品号,购买时间)。现要查询顾客A与顾客B购买的相同商品。有下列查询语句:
Ⅰ.
SELECT 商品号 FROM  购买表 WHERE 顾客号 = 'A'
AND 商品号 IN (SELECT 商品号 FROM  购买表 WHERE 顾客号 = 'B')
Ⅱ.
SELECT 商品号 FROM  购买表 WHERE 顾客号 = 'A'
        EXCEPT
SELECT 商品号 FROM  购买表 WHERE 顾客号 = 'B‘
Ⅲ.
SELECT 商品号 FROM  购买表 WHERE 顾客号 = 'A'
        INTERSECT
SELECT 商品号 FROM  购买表 WHERE 顾客号 = 'B'
Ⅳ.
SELECT 商品号 FROM  购买表 WHERE 顾客号 = 'A'
        UNION
SELECT 商品号 FROM  购买表 WHERE 顾客号 = 'B' 

上述语句中,能够实现该查询要求的是(  )。
A.仅Ⅰ和Ⅱ
B.仅Ⅰ和Ⅲ
C.仅Ⅰ和Ⅳ
D.仅Ⅲ
答案:B

3、

3.设有选课表(学号,课程号,成绩),现要统计每门课程的选课人数,并将结果保存到新表:选课情况表。下列语句中正确的是(      )。
A.
SELECT 课程号, COUNT(*) 选课人数 FROM 选课表 INTO 选课情况表GROUP BY 课程号
B.
SELECT 课程号, COUNT(*) 选课人数 INTO 选课情况表 FROM 选课表 GROUP BY 课程号
C.
SELECT 课程号, COUNT(*) FROM 选课表 INTO 选课情况表(课程号,选课人数)GROUP BY 课程号
D.
SELECT 课程号, COUNT(*) INTO 选课情况表(课程号, 选课人数)
FROM 选课表 GROUP BY 课程号
答案:B

4、

4.设某数据库中有学生表(学号,姓名,所在系)和选课表(学号,课程号,成绩)。现要查询没选课的学生姓名和所在系。下列语句中能够实现该查询要求的是(  )。
A.SELECT姓名,所在系FROM学生表a LEFT JOIN选课表b
ON a.学号=b.学号WHERE a.学号IS NULL
B.SELECT姓名,所在系FROM学生表a LEFT JOIN选课表b
ON a.学号=b.学号WHERE b.学号IS NULL
C.SELECT姓名,所在系FROM学生表a RIGHT JOIN选课表b
ON a.学号=b.学号WHERE a.学号IS NULL
D.SELECT姓名,所在系FROM学生表a RIGHT JOIN选课表b
ON a.学号=b.学号WHERE b.学号IS NULL
答案:B

5、

5.设在SQL Server2008中,用户U1在DB1数据库中创建了#Temp表。下列关于#Temp表的说法中,正确的是(  )。
A.在所有用户U1发起的连接中,都可以查询#Temp表数据
B.只有在创建#Temp表的连接中才可以查询#Temp表数据
C.在创建#Temp表的连接未断开时,DB1数据库的所有用户都可以查询#Temp表数据
D. 在创建#Temp表的连接断开时,DB1数据库的所有用户仍可以查询#Temp表数据
答案:B

6、

设在采用SQL Server 2008数据库的图书馆应用系统中有三个基本表,表结构如下所示,请用SQL语句完成下列两个查询:

BORROWER:

借书证号 姓名 系名 班级
12011106 蒋辉文 计算机系 12-1
12011107 王丽 计算机系 12-1
12012113 范园园 信息系 12-2
…… …… …… ……

LOANS:

借书证号 图书馆登记号 借书日期
12011106 T001001 2012.01.02
12012113 T001026 2013.02.06
…… …… ……

BOOKS:

索书号 书名 作者 图书登记号 出版社 价格
TP311.1 数据库系统 李明 T001001 科学 19.00
TP311.2 二级C语言 王珊 T001026 人民 32.00
…… …… …… …… …… ……

(1)检索至少借了5本书的同学的借书证号、姓名、系名和借书数。

(2)检索借书和王丽同学所借图书中的任意一本相同的学生姓名、系名、书名和借书日期。

1、

SELECT LOANS.借书证号,姓名,系名,COUNT(*) 
AS 借书数量
FROM BORROWER,LOANS
WHERE BORROWER.借书证号=LOANS.借书证号
GROUP BY LOANS.借书证号
HAVING COUNT(*)>=5;

2、

SELECT 姓名,系名,书名,借书日期
FROM  BORROWER,LOANS , BOOKS  
WHERE
 BORROWER.借书证号=LOANS.借书证号 
 AND LOANS.图书登记号=BOOKS.图书登记号
AND 索书号 IN
(
    SELECT 索书号 FROM BORROWER,LOANS,BOOKS 
    WHERE BORROW.借书证号=LOANS.借书证号 
    AND LOANS.图书馆登记号=BOOKS.图书登记号
    AND 姓名="王丽"
)

以上是关于第七章高级数据库查询的主要内容,如果未能解决你的问题,请参考以下文章

mysql学习第四天(高级查询)

高级数据结构第七章A . 数列(树状数组逆序对)

UNIX环境高级编程第七章

MyBatis高级特性

异常和TCP通讯

BPM-第七章-高级OOP特征