數據庫原理及應用【三】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.pswp.cn/news/383614.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/383614.shtml
英文地址,請注明出處:http://en.pswp.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;完整備份差…

數據庫原理及應用【五】安全性和完整性約束

數據庫一致性被破壞&#xff1a; 系統故障許多用戶的并發訪問人為破壞事務本身不正確 保護數據庫一致性的方法&#xff1a; 視圖/查詢修改訪問控制 普通用戶擁有資源特權的用戶DBA 數據庫的安全問題 身份驗證 口令物理設備 GRANT CONNECT TO John IDENTIFIED BY 123456…

遞歸式復雜度求解

代換法 猜測復雜度驗證是否滿足遞歸式&#xff08;使用歸納法&#xff09;找到常數應該滿足的條件針對基本情況&#xff0c;常數足夠大時總是成立的 需要注意的是&#xff0c;我們猜測的復雜度有可能不滿足遞歸式&#xff0c;這個時候就要通過減去一些低階項來使得歸納成立。…

斐波那契數列計算

定義 斐波那契數列&#xff1a; F[n]{0,n01,n1F[n?1]F[n?2],elseF[n] \begin{cases} 0,n0 \\ 1,n1\\ F[n-1]F[n-2],else \end{cases} F[n]??????0,n01,n1F[n?1]F[n?2],else? 樸素計算法 根據遞歸式F[n]F[n?1]F[n?2]F[n]F[n-1]F[n-2]F[n]F[n?1]F[n?2]進行計算…

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文件…

3.01【python正則表達式以及re模塊】

python正則表達式以及re模塊 元字符 正則表達式的語法就由表格中的元字符組成&#xff0c;一般用于搜索、替換、提取文本數據 元字符含義.匹配除換行符以外的任何單個字符*匹配前面的模式0次或1次匹配前面的模式1次或多次?匹配前面的模式0次或1次[]用于定義字符集&#xff…

Linux配置編程環境+云服務器上傳文件

Java環境配置 Ubuntu https://www.cnblogs.com/lfri/p/10437266.html Centos https://blog.csdn.net/qq_21077715/article/details/85536399 Tomcat配置 Centos https://blog.csdn.net/qq_21077715/article/details/85541685 https://www.cnblogs.com/newwind/p/9904561…

gbd + cgbd

gbd&#xff1a;傳送門 cgbd&#xff1a;傳送門 | 傳送門

數據可視化【十四】交互式過濾地區分布圖

在前面的博客中已經介紹了如何繪制地區分布圖&#xff0c;這一節學習如何繪制交互式過濾地區分布圖。如果對繪制地區分布圖還不熟悉的話可以了解一下之前我寫的博客&#xff1a;數據可視化【十三】地區分布圖 整體的框架仍然是在之前的基礎上進行修改&#xff0c;主要是添加交…

Ubuntu環境搭建

本文記錄了一些常用的Ubuntu軟件 然后首先修改軟件源&#xff1a;軟件和更新->Ubuntu軟件->下載自&#xff1a;其他站點&#xff08;修改為阿里云&#xff09; 在關閉的時候需要更新什么的 然后修改更新方式&#xff0c;將不支持的更新去掉 常用的Windows軟件 網易云…

1 兩數之和

雖然只是一道很簡單的題&#xff0c;但是也給我很多思考。 剛看到這道題的時候沒有仔細思考&#xff0c;直接寫了個排序和二分查找&#xff0c;想著對每個數字查找另一個數字會不會出現&#xff0c;復雜度是O(nlognnlogn)O(nlognnlogn)O(nlognnlogn)&#xff0c;主要訓練了一下…