数据库实验二 数据查询

一、实验目的
(1)掌握查询语句的一般格式;
(2)熟练掌握单表查询、连接查询、集合查询、统计查询和嵌套查询。
二、实验环境
PLSQL Developer 12
Oracle Database 11 home
三、实验步骤、出现的问题及解决方案
实验步骤:
1、查询“红楼梦”目前可借的各图书编号,及所属版本信息。(是否借出为‘否‘的图书)
SELECT 图书.图书编号,书目.ISBN,书目.书名,书目.作者,书目.出版单位
FROM 书目,图书
WHERE 书目.ISBN=图书.ISBN AND 书目.书名=‘红楼梦’ AND 是否借出=‘否’;
在这里插入图片描述
2、查找高等教育出版社的所有书目及单价,结果按单价降序排序。
SELECT *
FROM 书目
WHERE 出版单位=‘高等教育出版社’
ORDER BY 单价 DESC;
在这里插入图片描述
3、统计“红楼梦”各版的藏书数量(ISBN不同则版本不同)。
SELECT 书目.ISBN,COUNT(书目.ISBN)
FROM 书目,图书
WHERE 书目.ISBN=图书.ISBN AND 书目.书名=‘红楼梦’
GROUP BY 书目.ISBN;
在这里插入图片描述
4、查询学号“20061234”号借书证借阅未还的图书的信息。
SELECT 书目.*
FROM 书目,图书,借阅
WHERE 书目.ISBN=图书.ISBN AND 图书.图书编号=借阅.图书编号 AND 借阅.借书证号=‘20061234’;
在这里插入图片描述
5、查询各个出版社的图书最高单价、平均单价。
SELECT 书目.出版单位,MAX(单价),AVG(单价)
FROM 书目,图书
WHERE 书目.ISBN=图书.ISBN
GROUP BY 书目.出版单位;
在这里插入图片描述
6、要查询借阅了两本和两本以上图书的读者的个人信息。
SELECT 读者.*
FROM 读者
WHERE 读者.借书证号 IN
(
SELECT 借阅.借书证号
FROM 读者,借阅
WHERE 读者.借书证号=借阅.借书证号
GROUP BY 借阅.借书证号
HAVING COUNT()>=2
);
在这里插入图片描述
7、查询“王菲”的单位、所借图书的书名和借阅日期。
SELECT 书目.书名,借阅.借书日期
FROM 书目,图书,借阅
WHERE 书目.ISBN=图书.ISBN AND 图书.图书编号=借阅.图书编号 AND 借阅.借书证号 IN
(
SELECT 读者.借书证号
FROM 读者
WHERE 读者.单位=
(
SELECT 读者.单位
FROM 读者
WHERE 读者.姓名=‘王菲’
)
);
在这里插入图片描述
8、查询每类图书的册数和平均单价。
SELECT 图书分类.类名,COUNT(
),AVG(单价)
FROM 图书分类,书目,图书
WHERE 图书分类.图书分类号=书目.图书分类号 AND 书目.ISBN=图书.ISBN
GROUP BY 图书分类.类名;
在这里插入图片描述
9、统计从未借书的读者人数。
SELECT COUNT()
FROM 读者
WHERE 读者.借书证号 NOT IN
(
SELECT 借阅.借书证号
FROM 借阅
);
在这里插入图片描述
10、统计参与借书的人数。
SELECT COUNT(
)
FROM 读者
WHERE 读者.借书证号 IN
(
SELECT 借阅.借书证号
FROM 借阅
);
在这里插入图片描述
11、找出所有借书未还的读者的信息及所借图书编号及名称。
SELECT 读者.,图书.图书编号,书目.书名
FROM 读者,图书,书目,借阅
WHERE 图书.ISBN=书目.ISBN AND 借阅.图书编号=图书.图书编号 AND 借阅.借书证号=读者.借书证号 AND 借阅.归还日期 IS NULL;
在这里插入图片描述
12、检索书名是以“Internet”开头的所有图书的书名和作者。
SELECT 书目.书名,书目.作者
FROM 书目
WHERE REGEXP_LIKE(书目.书名,’^Internet’);
在这里插入图片描述
13、查询各图书的罚款总数。
SELECT 图书.图书编号,罚款.罚款总数
FROM 图书
LEFT JOIN
(
SELECT 借阅.图书编号,SUM(罚款分类.罚金) AS 罚款总数
FROM 借阅,罚款分类
WHERE 罚款分类.罚款分类号=借阅.罚款分类号
GROUP BY 借阅.图书编号
) 罚款
ON 罚款.图书编号=图书.图书编号;
数据库实验二 数据查询_第1张图片
14、查询借阅及罚款分类信息,如果有罚款则显示借阅信息及罚款名称、罚金,如果没有罚款则罚款名称、罚金显示空(左外连接)
SELECT 借阅.
,罚款分类.罚款名称,罚款分类.罚金
FROM 借阅
LEFT JOIN 罚款分类
ON 罚款分类.罚款分类号=借阅.罚款分类号;
数据库实验二 数据查询_第2张图片
15、查询借阅了所有“文学”类书目的读者的姓名、单位。
(1)方法一,双重否定表肯定,查询的读者不存在文学类的书没有借过
SELECT 读者.姓名,读者.单位
FROM 读者
WHERE NOT EXISTS
(
SELECT * FROM 图书分类,书目
WHERE 图书分类.图书分类号=书目.图书分类号 AND 图书分类.类名=‘文学’ AND NOT EXISTS
(
SELECT *
FROM 借阅,图书
WHERE 借阅.图书编号=图书.图书编号 AND 借阅.借书证号=读者.借书证号 AND 书目.ISBN=图书.ISBN
)
);
数据库实验二 数据查询_第3张图片
(2)方法二,查询的读者借的文学类书的数目(去重同一借书证借同一ISBN的文学书后的数目)等于文学类书的数目
SELECT 读者.姓名,读者.单位
FROM 读者
WHERE 读者.借书证号 IN
(
SELECT 读者文学类借书.借书证号
FROM
(
SELECT 文学借书数.借书证号,COUNT() AS 读者文学类数借书数
FROM
(
SELECT 借阅.借书证号,图书.ISBN
FROM 借阅,图书分类,书目,图书
WHERE 借阅.图书编号=图书.图书编号 AND 图书.ISBN=书目.ISBN AND 书目.图书分类号=图书分类.图书分类号 AND 图书分类.类名=‘文学’
GROUP BY (借阅.借书证号,图书.ISBN)
) 文学借书数
GROUP BY 文学借书数.借书证号
) 读者文学类借书,
(
SELECT COUNT(
) AS 总数
FROM 图书分类,书目
WHERE 图书分类.图书分类号=书目.图书分类号 AND 图书分类.类名=‘文学’
) 文学类书总数
WHERE 读者文学类借书.读者文学类数借书数=文学类书总数.总数
);
数据库实验二 数据查询_第4张图片
扩展:
1、在书目关系中新增“出版年份”,并在该属性下添加数据。
数据库实验二 数据查询_第5张图片

ALTER TABLE 书目 ADD 出版年份 VARCHAR(100);
UPDATE 书目 SET 出版年份=‘2005’ WHERE ISBN=‘7040195836’;
UPDATE 书目 SET 出版年份=‘1983’ WHERE ISBN=‘9787508040110’;
UPDATE 书目 SET 出版年份=‘2008’ WHERE ISBN=‘9787506336239’;
UPDATE 书目 SET 出版年份=‘2009’ WHERE ISBN=‘9787010073750’;
COMMIT;数据库实验二 数据查询_第6张图片
2、求总藏书量、藏书总金额、最高价、最低价。
SELECT COUNT(),SUM(单价),MAX(单价),MIN(单价)
FROM 书目,图书
WHERE 书目.ISBN=图书.ISBN;
在这里插入图片描述
3、列出藏书在5本以上的书目(书名、作者、出版社、出版年份)。
SELECT 书目.书名,书目.作者,书目.出版单位,书目.出版年份
FROM 书目
WHERE 书目.ISBN IN
(
SELECT 书目.ISBN
FROM 书目,图书
WHERE 书目.ISBN=图书.ISBN
GROUP BY 书目.ISBN
HAVING COUNT(
)>5
);
在这里插入图片描述
4、列出年份最久远的书?
SELECT *
FROM 书目
WHERE 书目.出版年份=
(
SELECT MAX(出版年份)
FROM 书目
);
在这里插入图片描述
5、 目前实际已借出多少册书?
SELECT COUNT()
FROM 图书
WHERE 图书.是否借出=‘是’;
在这里插入图片描述
6.、哪一年的图书最多?
SELECT 年份.出版年份
FROM
(
SELECT 书目.出版年份,COUNT(书目.出版年份) AS NUM
FROM 书目,图书
WHERE 书目.ISBN=图书.ISBN
GROUP BY 书目.出版年份
) 年份,
(
SELECT MAX(COUNT(
)) AS MAX
FROM 书目,图书
WHERE 书目.ISBN=图书.ISBN
GROUP BY 书目.出版年份
) 最多
WHERE 年份.NUM=最多.MAX;
在这里插入图片描述
7、 哪本借书证未归还的图书最多?
SELECT 统计.借书证号
FROM
(
SELECT MAX(COUNT(借阅.借书证号)) AS MAX
FROM 借阅
WHERE 借阅.归还日期 IS NULL
GROUP BY 借阅.借书证号
) 最多,
(
SELECT 借阅.借书证号,COUNT(借阅.借书证号) AS NUM
FROM 借阅
WHERE 借阅.归还日期 IS NULL
GROUP BY 借阅.借书证号
) 统计
WHERE 统计.NUM=最多.MAX;
数据库实验二 数据查询_第7张图片
8、平均每本借书证的借书册数。
SELECT SUM(借阅数.借阅_NUM/读者数.读者_NUM)
FROM
(
SELECT COUNT() AS 借阅_NUM
FROM 借阅
) 借阅数,
(
SELECT COUNT(
) AS 读者_NUM
FROM 读者
) 读者数;
在这里插入图片描述
9、哪个单位的读者平均借书册数最多?
SELECT 单位平均数.单位
FROM
(
SELECT 读者单位人数.单位,SUM(读者单位借书数.借书数/读者单位人数.人数) AS 平均数
FROM
(
SELECT 读者.单位,COUNT() AS 人数
FROM 读者
GROUP BY 读者.单位
) 读者单位人数,
(
SELECT 读者.单位,COUNT(
) AS 借书数
FROM 读者,借阅
WHERE 读者.借书证号=借阅.借书证号
GROUP BY 读者.单位
) 读者单位借书数
WHERE 读者单位人数.单位=读者单位借书数.单位
GROUP BY 读者单位人数.单位
) 单位平均数,
(
SELECT MAX(SUM(读者单位借书数.借书数/读者单位人数.人数)) AS 借书数
FROM
(
SELECT 读者.单位,COUNT() AS 人数
FROM 读者
GROUP BY 读者.单位
) 读者单位人数,
(
SELECT 读者.单位,COUNT(
) AS 借书数
FROM 读者,借阅
WHERE 读者.借书证号=借阅.借书证号
GROUP BY 读者.单位
) 读者单位借书数
WHERE 读者单位人数.单位=读者单位借书数.单位
GROUP BY 读者单位人数.单位
) 单位最多借书数
WHERE 单位平均数.平均数=单位最多借书数.借书数;
在这里插入图片描述
10、 最近两年都未被借过的书。
SELECT 图书.图书编号
FROM 图书
WHERE 图书.图书编号 NOT IN
(
SELECT 借阅.图书编号
FROM 借阅
WHERE MONTHS_BETWEEN(SYSDATE,借阅.借书日期)/12<=2
);
数据库实验二 数据查询_第8张图片
11、今年未借过书的借书证。
SELECT 读者.借书证号
FROM 读者
WHERE 读者.借书证号 NOT IN
(
SELECT 借阅.借书证号
FROM 借阅
WHERE 借阅.借书日期>
(
SELECT TRUNC(SYSDATE,‘YYYY’) FROM DUAL
)
);
数据库实验二 数据查询_第9张图片
出现的问题及解决方案:
1、无法调用派生表及聚集函数的列,解决方案:使用派生表中的列,需要给派生表取别名,才能在WHERE语句中调用,调用方法:别名.列名,如果子查询结果中使用了聚集函数,需要给聚集函数这列取别名,才能调用,调用时使用别名。表取别名不能用AS。
2、对15题,查询借阅了所有“文学”类书目的读者的姓名、单位,产生了错误的理解,题目的意思是查询到的读者要借阅了所有的文学类书,而不是借阅了文学类的书的读者有哪些,解决方案:
(1)方法一,双重否定表肯定,查询的读者不存在文学类的书没有借过
SELECT 读者.姓名,读者.单位
FROM 读者
WHERE NOT EXISTS
(
SELECT *
FROM 图书分类,书目
WHERE 图书分类.图书分类号=书目.图书分类号 AND 图书分类.类名=‘文学’ AND NOT EXISTS
(
SELECT *
FROM 借阅,图书
WHERE 借阅.图书编号=图书.图书编号 AND 借阅.借书证号=读者.借书证号 AND 书目.ISBN=图书.ISBN
)
);
(2)方法二,查询的读者借的文学类书的数目(去重同一借书证借同一ISBN的文学书后的数目)等于文学类书的数目
SELECT 读者.姓名,读者.单位
FROM 读者
WHERE 读者.借书证号 IN
(
SELECT 读者文学类借书.借书证号
FROM
(
SELECT 文学借书数.借书证号,COUNT() AS 读者文学类数借书数
FROM
(
SELECT 借阅.借书证号,图书.ISBN
FROM 借阅,图书分类,书目,图书
WHERE 借阅.图书编号=图书.图书编号 AND 图书.ISBN=书目.ISBN AND 书目.图书分类号=图书分类.图书分类号 AND 图书分类.类名=‘文学’
GROUP BY (借阅.借书证号,图书.ISBN)
) 文学借书数
GROUP BY 文学借书数.借书证号
) 读者文学类借书,
(
SELECT COUNT(
) AS 总数
FROM 图书分类,书目
WHERE 图书分类.图书分类号=书目.图书分类号 AND 图书分类.类名=‘文学’
) 文学类书总数
WHERE 读者文学类借书.读者文学类数借书数=文学类书总数.总数
);
3、ORACLE不支持使用DATEDIFF()函数计算时间差,解决方案:使用MONTHS_BETWEEN()方法来计算两个日期的月份之差,然后除以12,得到年份之差,就可以查询最近两年都未被借过的书了,MONTHS_BETWEEN()函数中的参数不能颠倒,否则会为负数。
4、怎么获取今年的第一天的日期?解决方案:使用TRUNC()函数将使用SYSDATE查询的日期从年份截去,就可以获取今年的第一天的日期,SELECT TRUNC(SYSDATE,‘YYYY’) FROM DUAL。
四、实验心得体会
通过本次实验熟练的掌握了查询的基本用法,对查询的嵌套有了更加深刻直观的认识,通过实验练习了一些难度较大的查询,对查询设计的思路更加清晰,知道该如何嵌套使用子查询以及怎样查询更清晰,不过也认识到了自己的不足,如15题,对于相关子查询掌握还不够好,思路不够清晰,理解不够透彻。

你可能感兴趣的:(数据库实验,数据库)