数据库原理及应用【三】DBMS+SQL

DBMS

  • Query Languages
  • Interface and maintaining tools(GUI)
  • APIs
  • Class Library

QL 不是图灵完备的,不是一种编程语言。

QL

SQL是一种非过程化的查询语言。

  • DDL数据定义语言:表,视图
  • QL 查询语言
  • DML 数据操纵语言
  • DCL 数据控制语言

Base table:基表,实际存在的表
View: 视图,不是实际存在的表,虚表

SELECT [DISTINCT] target_list
FROM ralation_list
WHERE qualification

Conceptual Evaluation Strategy

  • 计算笛卡尔乘积
  • WHERE子句做筛选
  • 根据target_list做投影
  • 根据是否有DISTINCT消除重复

在不引起混乱的情况下,多表查询可以不加别名。

使用distinct的时候需要注意,一般必须含有主键或者有unique约束的键。

SQL支持like表达的模糊查询

查询实例:

三张表:
Sailors :sid sname age rating
Boats : bid bname color
Reserves : sid bid day

create table Sailors
(sid int primary key,sname nvarchar(20) not null,rating int not null,age float
)go create table Boats
(bid int primary key,bname nvarchar(20) not null,color nvarchar(20) not null
)go create table Reserves
(sid int foreign key references Sailors(sid),bid int foreign key references Boats(bid),day date not null,primary key(sid, bid)
)goinsert into Sailors values (22,'dustin',7,45.0)
insert into Sailors values (31,'lubber',8,55.0)
insert into Sailors values (58,'rusty',10,35.0)
insert into Sailors values (28,'yuppy',9,35.0)
insert into Sailors values (44,'guppy',5,35.0)
insert into Sailors values(11,'dustin',8,20)insert into Boats values (101,'tiger','red')
insert into Boats values (103,'lion','green')
insert into Boats values (105,'hero','blue')insert into Reserves values (22,101,'1996-10-10')
insert into Reserves values (58,103,'1996-11-12')
insert into Reserves values (58,101,'1996-12-12')
insert into Reserves values(58,105,'1996-11-11')select * from Sailors
go
select * from Boats
go
select * from Reserves
SELECT S.age,age1 = S.age-5, 2*S.age As age2
FROM Sailors S
WHERE S.sname LIKE 'B_%B'--查找名字以B开头结尾且至少有三个字符的人的年龄

使用as给列起别名在有的系统中不适用。

查询预定过红色或者绿色船的水手信息:
使用or或者分别查询后使用union。需要注意的是使用union的两张表需要满足并兼容的条件。这里的两张表是满足的。

查询预订过红色和绿色船的水手信息:

  • Reserves的自连接
SELECT S.sid
FROM Sailors S, Boats B1, Reserves R1, Boats B2, Reserves R2
WHERE S.sid=R1.sid AND S.sid=R2.sid AND R1.bid=B1.bid AND R2.bid=B2.bid and (B1.color='red' AND B2.color='green')
  • 使用INTERSECT
SELECT S.sid
FROM Sailors S, Boats B, Reserves R
WHERE S.sid=R.sid AND B.bid=R.bid AND B.color='red'
INTERSECT
SELECT S.sid
FROM Sailors S, Boats B, Reserves R
WHERE S.sid=R.sid AND B.bid=R.bid AND B.color='green'

需要注意的是集合的交INTERSECT的两个表必须并兼容。

嵌套查询

预定过编号103号船的水手的姓名:
非关联子查询

SELECT S.sname
FROM Sailors S
WHERE S.sid IN ( SELECT R.sid FROM Reserves R WHERE R.bid=103)

关联嵌套子查询

SELECT S.sname
FROM Sailors S
WHERE EXISTS (SELECT *FROM Reserves RWHERE R.bid=103 AND S.sid=R.sid)

关联嵌套子查询的效率一般比非关联嵌套子查询的效率低。

在子查询中内层查询可以直接使用外层查询的值,相当于嵌套循环

预订过103号船并且只预订过一次船的水手的姓名:

SELECT S1.sname
FROM (SELECT *FROM Sailors SWHERE (SELECT COUNT(*) FROM Reserves R WHERE R.sid=S.sid)=2) S1
WHERE S1.sid IN(SELECT R.sid FROM Reserves R WHERE R.bid=103)

预订过103号船并且只预订过一次103号船的水手的姓名:


SELECT S.sname
FROM Sailors S
WHERE ((SELECT COUNT(*) FROM Reserves R WHERE R.sid=S.sid AND R.bid=103)=1)

查找只有一个人预订的船:
不使用COUNT的方法:从Resevers得到所有没有被其他人订过的船

SELECT B.bname
FROM Boats B,Reserves R1
WHERE B.bid=R1.bid AND B.bid NOT IN (SELECT R2.bid FROM Reserves R2 WHERE R2.sid<>R1.sid)

使用COUNT的方法:

SELECT B.bname
FROM Boats B
WHERE (SELECT COUNT(*) FROM (SELECT DISTINCT R.bid,R.sid FROM Reserves R) R WHERE R.bid=B.bid)=1

还可以使用UNIQUENOT UNIQUE

ANY ALL

找到比任意一个叫dustin的级别高的人的姓名

SELECT *
FROM Sailors S
WHERE S.rating > ANY (SELECT S2.rating FROM Sailors S2 WHERE S2.sname='dustin')

找到比所有叫dustin的级别高的人的姓名

SELECT *
FROM Sailors S
WHERE S.rating > ALL (SELECT S2.rating FROM Sailors S2 WHERE S2.sname='dustin')

查找某个表中同时满足另一个表所有条件的信息的时候使用除法

查找预订过所有船的水手的姓名

  • Solution 1:否定之否定,使用EXCEPT
SELECT S.sname
FROM Sailors S
WHERE NOT EXISTS((SELECT B.bid FROM Boats B)EXCEPT	--集合差(SELECT R.bid FROM Reserves R WHERE R.sid=S.sid))
  • Solution 2:不使用EXCEPT
--不存在有船他没有租过的人
SELECT S.sname
FROM Sailors S
WHERE NOT EXISTS(SELECT * FROM Boats B WHERE B.bid NOT IN (SELECT R.bid FROM Reserves R WHERE R.sid=s.sid))--等价于
SELECT S.sname
FROM Sailors S
WHERE NOT EXISTS(SELECT * FROM Boats B WHERE  NOT EXISTS (SELECT * FROM Reserves R WHERE R.sid=s.sid AND R.bid=B.bid))

聚合函数

  • COUNT(*)
  • COUNT([DISTINCT] A)查询属性A有多少个不同的值
  • SUM([DISTINCT] A )对(不同的)属性A进行求和
  • AVG([DISTINCT] A)对(不同的)属性A求平均值
  • MIN(A)
  • MAX(A)
SELECT COUNT(DISTINCT S.rating)
FROM Sailors S
WHERE S.name='Bob'

分组聚集group by

SELECT [DISTINCT] target-list
FROM relation-list
WHERE qualification
GROUP BY grouping-list
HAVING group-qualification

首先对from子句对表进行笛卡尔乘积,根据where子句对元组进行筛选,对筛选的结果根据group-by的值相同条件进行分组,然后对计算的结果根据having后的条件对分组进行筛选,最后再根据分组计算select子句后面的值,这要求select和having后的值对每个组都是单一的(是分组属性集的子集)。

SQL无法简单的从语法上确定。

有了group by 以后,计算是在分组上进行的,如果没有,是在表上进行的。

分组其实是做排序,然后再将值相同的分组。

SELECT S.rating,MIN(S.age) as minage
FROM Sailors S
WHERE S.age>=18
GROUP BY S.rating
HAVING COUNT(*)>1 AND EVERY(S.age<=60)--EVERY对应的还有ANY

EVERY要求每个分组的每个元素都必须满足要求,ANY要求每个分组至少有一个元素满足要求

查询每一条红船的预订人数:

SELECT B.bid,COUNT(*) AS scount
FROM Boats B,Resevers R
WHERE R.bid=B.bid AND B.color='red'
GROUP BY B.bid

下面的语句会报错:

SELECT B.bid,COUNT(*) AS scount
FROM Boats B,Resevers R
WHERE R.bid=B.bid
GROUP BY B.bid
HAVING B.color='red'

报错的原因是数据库的语法检查比较简单,不会按照业务的语义来进行判断,只会简单的判断SELECTHAVING后面的子句有没有在GROUP BY后面出现

因为这里的每一种船只有一种颜色,因此我们可以在聚合的时候加上B.color条件,这样上面的查询就可以了。

SELECT B.bid,COUNT(*) AS scount
FROM Boats B,Reserves R
WHERE R.bid=B.bid
GROUP BY B.bid,B.color
HAVING B.color='red'

对于每个至少有两个人的级别,找出年龄大于18岁的最小年龄。

SELECT S.rating, MIN(S.age)
FROM Sailors S
WHERE S.age > 18
GROUP BY S.rating
HAVING 1<(SELECT COUNT(*) FROM Sailors S1 WHERE S1.rating=S.rating)

对于组中属性的筛选只能通过WHERE子句,筛选过的元组再进行分组的时候需要对分组进行筛选,但是这里的分组已经不是以前的分组了,因此需要在子句中再使用子查询。

查找平均年龄最小的级别:

SELECT top 1 S.rating,AVG(S.age) as 'avgAge'
FROM Sailors S
GROUP BY S.rating
ORDER BY avgAge

NULL值

不是0,不是"",是不知道。

Case表达式

--Officers(name,status,rank,title)
SELECT name,Case statusWHEN 1 THEN 'Active Duty'WHEN 2 THEN 'Reserve'WHEN 3 THEN 'Special Assignment'WHEN 4 THEN 'Retired'ELSE 'Unknown'END AS status
FROM Officers
--Machines(serialno, type, year, hours_used, accidents)
--Find the rate of the accidents of "chain saw" in the whole accidentsSELECT sum(CASE WHEN type='chain saw' THEN accidentsELSE 0e0END)/sum(accidents)
FROM Machines

注意如果CASE后面有字段名,则WHEN后面应该是该字段名的值的情况,如果没有的话WHEN后面应该是布尔表达式

还需要注意的是可以同时对两个聚合函数的值进行运算。

--查找每种设备的平均故障率SELECT type,CASE WHEN sum(hours_used)>0 THEN sum(accidents)/sum(hours_used)ELSE NULLEND AS accident_rate
FROM Machines
GROUP BY type

上面的查询语句使用CASE语句的主要原因是可能有的设备没有使用过,因此没有故障率一说。如果非要计算的话有可能导致分母为0的情况。

CASE语句对于需要分情况处理的语句效果比较好。

对于含有GROUP BY语句的查询,需要把SELECT里面的语句都对分组后进行处理。

对于上面的语句我们当然也可以在HAVING语句中对组进行筛选后再进行计算,可是这样做的话就无法得到那些没有时长的组的信息。

子查询:

标量子查询:查询的结果是一个值,一般使用聚合函数

在SQL语句中,凡是可以出现一个值的地方,都可以出现标量子查询。

SELECT d.deptno,d.deptname,(SELECT MAX(salary)FROM empWHERE deptno=d.deptno) as maxpay
FROM dept as d
WHERE d.location='NEW YORK'

SELECT语句中也可以使用子查询。
当然我们也可以使用联表查询。

表表达式:查询的结果又是一张表

SELECT startyear,avg(pay)
FROM (SELECT name,salary+bonus as pay, year(startdate) as startyearFROM emp )as emp2
GROUP BY startyear

FROM子句中也可以出现子查询,但是需要注意的是不可以在该语句的其他子查询直接使用该子查询得到的临时表。
表表达式一般出现在FROM子句中

公共表表达式:如果多次使用同一个,只定义一次,多次使用

WITH子句定义公共子表达式,其实是一个临时视图

--寻找部门总收入最高的部门
WITH payroll(deptno,totalpay) AS(SELECT deptno,sum(salary)+sum(bonus)FROM empGROUP BY deptno)
SELECT deptno
FROM payroll
WHERE totalpay = (SELECT max(totalpay) FROM payroll)
--查找一个部门对,第一个部门的平均工资大于第二个的两倍
WITH deptavg(deptno,avgsal) AS(SELECT deptno,avg(salary)FROM empGROUP BY deptno)
SELECT d1.deptno,d1.avgsal,d2.deptno,d2.avgsal
FROM deptavg AS d1, deptavg AS d2
WHERE d1.avgsal>2*d2.avgsal

需要注意的是WITHSELECT之间没有没有逗号,整个合在一起是一条语句

外连接

有两种集合差操作:

  • EXCEPT:会消除重复元组,需要排序
  • EXCEPT ALL:如果确信不会出现重复元组或者重复元组对结果没有影响就是用这个,效率更高
    在这里插入图片描述

在这里插入图片描述在这里插入图片描述

上面所有都是一条SQL语句。

递归查询

联邦雇员FedEmp(name,salary,manager)

找到胡佛手下超过10万员的雇员(包括简接雇员)

WITH agents(name,salary) AS((SELECT name,salary)FROM empWHERE manager='Hoover')UNION ALL(SELECT f.name,f.salaryFROM agents as a,FedEmp as fWHERE f.manager=a.name))
SELECT name FROM agents WHERE salary>100000

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

DML

INSERT INTO table-name VALUES (); --插入一条元组
DELETE FROM table-name WHERE 条件
UPDATE table-list SET 字段名='' WHERE 条件

VIEW

  • 普通视图
CREATE VIEW view-name AS (SELECT 语句)

视图的定义会进行保存
- 虚表
- 实现数据的逻辑独立性
- 数据安全性
- 视图更新问题:早期系统不能进行更新。如果视图中的信息可以和基表中的信心一一对应,唯一映射的话,就可以进行修改。不同产品可能不同。

  • 临时视图
    定义不会进行保存,支持递归查询
WITH table-list() AS ()

程序设计语言访问数据库

嵌入式SQL

  • EXEC SQL开始,以;结束

应用API:ODBC——>JDBC

类库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/383614.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据可视化【五】 Scatter Plot

Scatter Plot vizhub上实现的代码&#xff1a; https://vizhub.com/Edward-Elric233/53807a1b35d94329b3689081cd2ea945 https://vizhub.com/Edward-Elric233/b9647d50899a4a0e8e917f913cd0a53a https://vizhub.com/Edward-Elric233/8c6b50cd81a04f048f490f48e4fe6264 由前…

数据可视化【六】Line Chart Area Chart

Line Chart vizhub代码&#xff1a; https://vizhub.com/Edward-Elric233/094396fc7a164c828a4a8c2e13045308 实现效果&#xff1a; 这里先使用d3.line()设置每个点的x坐标和y坐标&#xff0c;然后再用这个东西设置path的d属性&#xff0c;就可以得到曲线。 const lineGen…

数据可视化【七】 更新模式

Enter 以下面这个简单的代码进行分析 const svg d3.select(svg); // svg.style(background-color, red); testconst height svg.attr(height); // equals paresFloat() const width svg.attr(width);const makeFruit type >( {type} ); //这种写法好像能够直接得到一个…

数据可视化【八】根据数据类型选择可视化方式

Marks:Rows PointsLinesAreas Channels:Columns PositionColorShape

数据可视化【九】单向数据流交互

我们使用一下上上篇博客的代码。 例如我们想要当鼠标点击水果的时候会出现黑色的框&#xff0c;再点击一下黑色的框就会消失。 首先&#xff0c;我们应该给组件添加点击事件&#xff1a; fruitBowl.js gruopAll.on(click, d > onClick(d.id));这个on函数第一个参数是事件…

数据库原理及应用【四】数据库管理系统

查询优化 数据库管理系统中非常重要的一部分。 代数优化 按照一定的规则将语句变化成关系代数以后进行优化 操作优化 对代数优化后的查询树使用比较好的方法进行查询。 主要是对连接运算进行优化 嵌套循环归并扫描索引优化哈希连接 恢复机制 备份&#xff08;完整备份差…

递归式复杂度求解

代换法 猜测复杂度验证是否满足递归式&#xff08;使用归纳法&#xff09;找到常数应该满足的条件针对基本情况&#xff0c;常数足够大时总是成立的 需要注意的是&#xff0c;我们猜测的复杂度有可能不满足递归式&#xff0c;这个时候就要通过减去一些低阶项来使得归纳成立。…

P、NP、NP完全问题、NP难问题

可以在多项式时间内求解的问题称为易解的&#xff0c;而不能在多项式时间内求解的问题称为难解的。 P类问题&#xff1a;多项式类型&#xff0c;是一类能够用&#xff08;确定性的&#xff09;算法在多项式的时间内求解的判定问题。 只有判定问题才属于P 不可判定问题&#…

数据可视化【十】绘制地图

Loading and parsing TOPOJSON 导入Topojson d3文件 地址&#xff1a;https://unpkg.com/topojson3.0.2/dist/topojson.min.js 想要找d3文件的话去unpkg.com好像大部分都能找到的样子 Rendering geographic features 寻找合适的地图数据&#xff1a;谷歌搜索world-atlas npm…

数据可视化【十一】树状图

Constructing a node-link tree visualization 首先将节点之间的连线画出来。 使用json函数读取文件以后&#xff0c;使用hierarchy等函数得到连线的数组&#xff0c;然后绑定这个数组&#xff0c;给每个元素添加一个path&#xff0c;绘画使用的是一个函数linkHorizontal&…

数据可视化【十二】 颜色图例和尺寸图例

有了前面的知识&#xff0c;制作一个图例应该不是很难&#xff0c;关键是我们想要制作一个可以在其他地方进行使用的图例&#xff0c;这样就需要能够动态地设置图例的大小&#xff0c;位置&#xff0c;等等。 这里直接上代码&#xff1a; colorLegend.js export const color…

数据可视化【十三】地区分布图

在前面的博客中已经介绍了如何绘制地图&#xff0c;这一节学习如何绘制地区分布图。如果对绘制地图还不熟悉的话可以了解一下之前我写的博客&#xff1a;数据可视化【十】绘制地图 Intergrating(整合) TopoJSON with tabular data(列表数据) 在前面的博客中没有使用到tsv文件…

数据可视化【十四】交互式过滤地区分布图

在前面的博客中已经介绍了如何绘制地区分布图&#xff0c;这一节学习如何绘制交互式过滤地区分布图。如果对绘制地区分布图还不熟悉的话可以了解一下之前我写的博客&#xff1a;数据可视化【十三】地区分布图 整体的框架仍然是在之前的基础上进行修改&#xff0c;主要是添加交…

Ubuntu环境搭建

本文记录了一些常用的Ubuntu软件 然后首先修改软件源&#xff1a;软件和更新->Ubuntu软件->下载自&#xff1a;其他站点&#xff08;修改为阿里云&#xff09; 在关闭的时候需要更新什么的 然后修改更新方式&#xff0c;将不支持的更新去掉 常用的Windows软件 网易云…

Ubuntu修改/删除主目录下的中文文件夹

在Ubuntu的主目录下一般是有一些中文的目录&#xff0c;例如桌面&#xff0c;视频等等&#xff0c;还无法修改名称&#xff0c;在一群英文文件夹里面显得有些突兀&#xff08;Ubuntu终端下的中文一点也不好看&#xff09;&#xff0c;就想把这些文件夹修改一下&#xff0c;结果…

每日一题:leetcode1489. 找到最小生成树里的关键边和伪关键边

时隔多年我终于又开始写博客了&#xff0c;主要是已经放假了&#xff0c;之前一直忙于考试和课设没有时间写博客&#xff0c;学习笔记也因为买了iPad的缘故大部分都是手写的了。 假期想要把以前做过的项目都整理一下放在github和CSDN上。 也已经很久没有写算法题了&#xff0…

每日一题:leetcode989.数组形式的整数加法

题目描述 题目分析 题目非常简单&#xff0c;但是我还是wa了几发&#xff0c;对不起&#xff0c;我太菜了。我的想法是把K转换为数组然后用大整数加法处理。但是因为太久没有写了导致写了好久。 class Solution { public:void add(vector<int> &A, vector<int&g…

每日一题:leetcode674.最长连续递增序列

题目描述 题目分析 一遍遍历&#xff0c;如果硬要说用了什么算法的话觉得应该算是一个简单的滑动窗口吧 AC代码 class Solution { public:int findLengthOfLCIS(vector<int>& nums) {if (nums.size() 0) {return 0;}int ret 1;int cnt 1;for (int i 1; i <…

每日一题:leetcode959.由斜杠划分区域

题目描述 题目分析 仔细分析这道题以后虽然觉得可能要转化为图之类的&#xff0c;但是完全没有具体的想法&#xff0c;因为每个格子都有三种情况&#xff0c;这三种情况的不同的组合又会产生不同的结果。 发现找不到编码转化为图以后&#xff0c;我分析了一下不同数量方块之间…

每日一题:leetcode1319.联通网络的操作次数

题目描述 题目分析 ps&#xff1a;这篇博客是补前天的&#xff0c;前天在老家不方便写博客 题目挺简单的&#xff0c;但是通过题目对图的连通性有了一个更深刻的认识&#xff1a;如果有超过&#xff08;或等于&#xff09;n-1条边&#xff0c;则一定是可以让整个图联通的。 如…