我想網關鍵詞優(yōu)化舉例
目錄
- 實驗目的
- 實驗內容
- 實驗要求
- 實驗過程
- 實驗代碼
- 結果示意
書接上文,但是感覺之前的形式不太好用,至少不是很方便觀看,所以這篇嘗試改變一下寫法,希望可以提升一些觀感
實驗目的
(1) 掌握RDBMS的數據多表查詢功能
(2) 掌握SQL語言的數據多表查詢語句
實驗內容
(1) 等值連接查詢(含自然連接查詢)與非等值連接查詢
(2) 自身連接查詢
(3) 外連接查詢
(4) 復合條件連接查詢
(5) 嵌套查詢(帶有IN謂詞的子查詢)
(6) 嵌套查詢(帶有比較運算符的子查詢)
(7) 嵌套查詢(帶有ANY或ALL謂詞的子查詢)
(8) 嵌套查詢(帶有EXISTS謂詞的子查詢)
(9) 集合查詢
實驗要求
(1) 熟練掌握SQL的連接查詢語句
(2) 熟練掌握SQL的嵌套查詢語句
(3) 掌握表名前綴、別名前綴的用法
(4) 掌握不相關子查詢和相關子查詢的區(qū)別和用法
(5) 掌握不同查詢之間的等價替換方法(一題多解)及限制記錄實驗結果,認真完成實驗報告
實驗過程
建立示例數據庫S_T(復習)
表Student
學號
Sno 姓名
Sname 性別
Ssex 年齡
Sage 所在系
Sdept
200215121 李勇 男 20 CS
200215122 劉晨 女 19 CS
200215123 王敏 女 18 MA
200215125 張立 男 19 IS
表Course
課程號
Cno 課程名
Cname 現行課
Cpno 學分
Ccredit
1 數據庫 5 4
2 數學 2
3 信息系統 5 4
4 操作系統 6 3
5 數據結構 7 4
6 數據處理 2
7 PASCAL語言 6 4
表SC
學號
Sno 課程號
Cno 成績
Grade
200215121 1 92
200215121 2 85
200215121 3 88
200215122 2 90
200215122 3 80
實驗代碼
在SQL Server集成管理器的查詢窗口中輸入如下SQL語句序列來創(chuàng)建示例數據庫。
/* 創(chuàng)建示例數據庫S_T,包括3個表,即學生表Student、課程表Course和選課表SC*/
create database S_T;
go
use S_T; /*將S_T設為當前數據庫*/
create table Student(Sno CHAR(9) PRIMARY KEY,Sname CHAR(20) UNIQUE,Ssex CHAR(2),Sage SMALLINT,Sdept CHAR(20));
go
/表Student的主碼為Sno,屬性列Sname取唯一值/
create table Course(Cno CHAR(4) PRIMARY KEY,Cname CHAR(40),Cpno CHAR(4),Ccredit SMALLINT,FOREIGN KEY (Cpno) REFERENCES Course(Cno));
go
/表Course的主碼為Cno,屬性列Cpno(先修課)為外碼,被參照表為Course,被參照列是Cno/
create table SC(Sno CHAR(9),Cno CHAR(4),Grade SMALLINT,primary key (Sno, Cno),FOREIGN KEY (Sno) REFERENCES Student(Sno),FOREIGN KEY (Cno) REFERENCES Course(Cno));
go
/表SC的主碼為(Sno, Cno), Sno和Cno均為外碼,被參照表分別為Student和Course,被參照列分別為Student.Sno和Course.Cno/
insert into student values('200215121','李勇','男',20,'CS');
insert into student values('200215122','劉晨','女',19,'CS');
insert into student values('200215123','王敏','女',18,'MA');
insert into student values('200215125','張立','男',19,'IS');
go
/為表Student添加數據/
insert into course values('1', '數據庫', NULL,4);
insert into course values('2', '數學', NULL,2);
insert into course values('3', '信息系統', NULL,4);
insert into course values('4', '操作系統', NULL,3);
insert into course values('5', '數據結構', NULL,4);
insert into course values('6', '數據處理', NULL, 2);
insert into course values('7', 'PASCAL語言', NULL,4);
go
update Course set Cpno = '5' where Cno = '1';
update Course set Cpno = '1' where Cno = '3';
update Course set Cpno = '6' where Cno = '4';
update Course set Cpno = '7' where Cno = '5';
update Course set Cpno = '6' where Cno = '7';
go
/為表Course添加數據/
insert into SC values('200215121', '1',92);
insert into SC values('200215121', '2',85);
insert into SC values('200215121', '3',88);
insert into SC values('200215122', '2',90);
insert into SC values('200215122', '3',80);
go
也可以將上述SQL語句序列預先保存在S_T.sql文件中,在SSMS中打開并執(zhí)行該文件中的sql語句序列
對學生關系Student、課程關系Course和選修關系SC進行多表查詢
基本練習
(1)等值連接查詢與自然連接查詢
例如:查詢每個學生及其選修課的情況。
SELECT Student.*, SC.*
FROM Student, SC
WHERE Student.Sno = SC.Sno; /* 一般等值連接 */
又如:查詢每個學生及其選修課的情況(去掉重復列)
SELECT Student.Sno, Sname, Ssex, Sage, Cno, Grade
FROM Student, SC
WHERE Student.Sno = SC.Sno; /* 自然連接--特殊的等值連接 */
(2)自身連接查詢
例如:查詢每一門課的間接先修課。
SELECT FIRST.Cno, SECOND.Cpno
FROM Course FIRST, Course SECOND
WHERE FIRST.Cpno = SECOND.Cno;
(3)外連接查詢
例如:查詢每個學生及其選修課的情況(要求輸出所有學生–含未選修課程的學生的情況)
SELECT Student.Sno, Sname, Ssex, Sage, Sdept, Cno, Grade
FROM Student LEFT OUTER JOIN SC ON(Student.Sno = SC.Sno);
(4)復合條件連接查詢
例如:查詢選修了2號課程而且成績在90以上的所有學生的學號和姓名。
SELECT Student.Sno,Sname
FROM Student,SC
WHERE Student.Sno = SC.Sno ANDSC.Cno = '2' AND SC.Grade >= 90;
又如:查詢每個學生的學號、姓名、選修的課程名及成績。
SELECT Student.Sno, Sname, Cname, Grade
FROM Student, SC, Course
WHERE Student.Sno = SC.Sno ANDSC.Cno = Course.Cno;
(5)嵌套查詢(帶有IN謂詞的子查詢)
例如:查詢與“劉晨”在同一個系學習的學生的學號、姓名和所在系。
SELECT Sno, Sname, Sdept
FROM Student
WHERE Sdept IN (SELECT SdeptFROM StudentWHERE Sname = '劉晨'); /* 解法一*/
可以將本查詢中的IN謂詞用比較運算符‘=’來代替:
SELECT Sno, Sname, Sdept
FROM Student
WHERE Sdept = (SELECT SdeptFROM StudentWHERE Sname = '劉晨'); /* 解法二*/```
也可以使用自身連接完成以上查詢:
```sql
SELECT s1.Sno, s1.Sname, s1.Sdept
FROM Student s1, Student s2
WHERE s1.Sdept = S2.Sdept AND s2.Sname = '劉晨'; /* 解法三*/
還可以使用EXISTS謂詞完成本查詢:
SELECT Sno, Sname, Sdept
FROM Student S1
WHERE EXISTS(SELECT *FROM Student S2WHERE S2.Sdept=S1.Sdept AND S2.Sname='劉晨'); /* 解法四*/
又如:查詢選修了課程名為“信息系統”的學生號和姓名。
SELECT Sno, Sname
FROM Student
WHERE Sno IN (SELECT SnoFROM SCWHERE Cno IN(SELECT CnoFROM CourseWHERE Cname = '信息系統'));```
也可以使用連接查詢來完成上述查詢:
```sql
SELECT Student.Sno, Sname
FROM Student, SC, Course
WHERE Student.Sno = SC.Sno ANDSC.Cno = Course.Cno ANDCourse.Cname = '信息系統';
(6)嵌套查詢(帶有比較運算符的子查詢)
例如:找出每個學生超過他所選修課程平均成績的課程號。
SELECT Sno, Cno
FROM SC x
WHERE Grade >= ( SELECT AVG(Grade)FROM SC yWHERE y.Sno = x.Sno);
(7)嵌套查詢(帶有ANY或ALL謂詞的子查詢)
例如:查詢其他系中比計算機系某個學生年齡小的學生的姓名和年齡。
SELECT Sname, Sage
FROM Student
WHERE Sage <ANY (SELECT SageFROM StudentWHERE Sdept = 'CS')AND Sdept <> 'CS';
本查詢也可以使用聚集函數來實現:
SELECT Sname, Sage
FROM Student
WHERE Sage < (SELECT MAX(Sage)FROM StudentWHERE Sdept = 'CS')AND Sdept <> 'CS';
又如:查詢其他系中比計算機系所有學生年齡都小的學生的姓名和年齡。
SELECT Sname, Sage
FROM Student
WHERE Sage <ALL (SELECT SageFROM StudentWHERE Sdept = 'CS')AND Sdept <> 'CS';
也可以使用聚集函數來實現:
SELECT Sname, Sage
FROM Student
WHERE Sage < (SELECT MIN(Sage)FROM StudentWHERE Sdept = 'CS')AND Sdept <> 'CS';
(8)嵌套查詢(帶有EXISTS謂詞的子查詢)
例如:查詢所有選修了1號課程的學生姓名。
111sqlSELECT Sname
FROM Student
WHERE EXISTS
(SELECT *
FROM SC
WHERE Sno=Student.Sno AND Cno=‘1’);
又如:查詢所有未選修1號課程的學生姓名。
```sql
SELECT Sname
FROM Student
WHERE NOT EXISTS(SELECT *FROM SCWHERE Sno=Student.Sno AND Cno='1');
可以使用帶有EXISTS謂詞的子查詢實現全稱量詞或蘊涵邏輯運算功能:
例如:查詢選修了全部課程的學生姓名。
SELECT Sname
FROM Student
WHERE NOT EXISTS(SELECT *FROM CourseWHERE NOT EXISTS(SELECT *FROM SCWHERE Sno=Student.Sno ANDCno=Course.Cno));
又如:查詢至少選修了學生200215122選修的全部課程的學生號碼。
SELECT DISTINCT Sno
FROM SC SCX
WHERE NOT EXISTS(SELECT *FROM SC SCYWHERE SCY.Sno='200215122' ANDNOT EXISTS(SELECT *FROM SC SCZWHERE SCZ.Sno=SCX.Sno ANDSCZ.Cno=SCY.Cno));
(9)集合查詢
例如:查詢計算機系的學生以及年齡不大于19歲的的學生。
SELECT *
FROM Student
WHERE Sdept='CS'
UNION /*并集運算*/
SELECT *
FROM Student
WHERE Sage<=19;
可以改用多重條件查詢:
SELECT *
FROM Student
WHERE Sdept='CS' OR Sage<=19;
又如:查詢既選修了課程1又選修了課程2的學生(交集運算)。
SELECT Sno
FROM SC
WHERE Cno='1'
INTERSECT /*交集運算*/
SELECT Sno
FROM SC
WHERE Cno='2';
可以使用嵌套查詢:
SELECT Sno
FROM SC
WHERE Cno='1' AND Sno IN(SELECT SnoFROM SCWHERE Cno='2');
思考:能不能改用多重條件查詢?
SELECT Sno
FROM SC
WHERE Cno='1' AND Cno='2';
再如:查詢計算機系的學生與年齡不大于19歲的學生的差集。
SELECT *
FROM Student
WHERE Sdept='CS'
EXCEPT /*差集運算*/
SELECT *
FROM Student
WHERE Sage<=19;
可以改用多重條件查詢:
SELECT *
FROM Student
WHERE Sdept='CS' AND Sage>19;
結果示意