SQL Server數據庫第六課:使用group by和having進行分組查詢、多表連接查詢的使用

知識點:group by進行分組查詢、having子句進行分組查詢、多表連接查詢的使用。

 

1、使用SQL語句創建多表(本章學習的準備工作)

        使用SQL語句單獨創建數據庫、創建表,我們都會了,那麼當兩個表有關係的時候,怎麼創建呢?引用外鍵約束的時候,如何使用SQL語句?

思考:

①分清楚兩個表之間的關係(主表和從表、主鍵和外鍵)

②分清楚從表中的哪個鍵進行引用,引用的是主表中的主鍵列

③引用外鍵的列在SQL語句中如何寫( 從表列名 類型 references 主表(主鍵列名

實現思路:

(1)創建數據庫StudentDB、使用數據庫StudentDB、

(2)創建表Class、向表中插入班級信息.

(3)創建表Student(從表),Class_id引用主表的id(主鍵)

--創建數據庫StudentDB
create database StudentDB;
--使用數據庫
use StudentDB;
--創建表:班級表(編號、班級、人數)
create table Class(
	id int primary key,              --編號      整數 主鍵
	class char(20) unique not null,  --班級      字符 唯一鍵 非空 
	stu_numbers int not null         --班級人數  整數  非空
);
--向班級表中插入數據
insert into Class(id,class,stu_numbers)
select 1,'1831308',52 union
select 2,'1831309',48 union
select 3,'1831310',47 union
select 4,'1831311',44
--創建學生表(從表,班級列引用主表的主鍵)
create table Student(
	Id int primary key,                  --編號 整數 主鍵
	Class_id int references Class(id),   --班級 整數 外鍵(引用班級表class裏的主鍵id)
	SchoolNumber int unique not null,    --學號 整數 唯一鍵
	Names nvarchar(30) not null,         --姓名 字符 非空
	Age int,                             --年齡 整數
	Sex char(2),                         --性別 字符
	Score float                          --分數 浮點數
);
--向學生表中插入數據
insert into Student(Id,Class_id,SchoolNumber,Names,Age,Sex,Score)
select 1,2,1001,'張傑',18,'男',78.5 union
select 2,1,1002,'謝娜',19,'女',58 union
select 3,1,1003,'李連杰',22,'男',89 union
select 4,3,1004,'張揚',21,'男',90 union
select 5,2,1005,'歐娜娜',18,'女',60 union
select 6,4,1006,'關曉彤',21,'女',87 union
select 7,1,1007,'李易峯',22,'男',73 union
select 8,3,1008,'關彤彤',23,'女',93 union
select 9,1,1009,'李四',17,'男',69 union
select 10,4,1010,'張三',18,'女',88.5

 

2、使用group by進行分組查詢

  • 要求1:查詢school數據庫中表student中的總分數
  • 要求2:統計男生和女生的總分數如何進行?思考:先按照性別進行男生女生分組,然後再利用sum()函數進行求和。
  • 要求3:統計不同年級,男生和女生的總分數,並且按照總分數從高往低進行排序如何進行?思考:先按照年級和性別分組,然後再利用sum()函數進行求和,最後按照求和結果進行降序排列。
--使用group by進行分組查詢
--要求1:查詢school數據庫中表student中的總分數
select sum(Score) as 總分數 from Student;
--要求2:統計男生和女生的總分數如何進行?思考:先按照性別進行男生女生分組,然後再利用sum()函數進行求和。
select Sex 性別,sum(Score) 總分數 from Student group by Sex;
--要求3:統計不同年級,男生和女生的總分數,並且按照總分數從高往低進行排序如何進行?思考:先按照年級和性別分組,然後再利用sum()函數進行求和,最後按照求和結果進行降序排列。
select Sex,Class_id, sum(score) as 總分數 from Student 
group by Sex, Class_id 
order by sum(score) desc;

使用場景:需要對數據進行分組統計時。沒有使用聚合函數的列都要被group by

舉例,查詢男生女生各有多少人:select sex 性別,count(*) 總人數 from Stu group by sex;

注意:在使用group by 關鍵字時,在select列表中可以指定的列是有限制的,僅允許以下幾項:

  1. 被分組的列
  2. 爲每個分組返回一個值的表達式,如聚合函數計算出的列。

 

3、使用having子句進行分組篩選

  • 要求1:統計不同班級的學生總分數
  • 要求2:查詢班級總分數超過220的班級?思考能否使用where?會報錯因爲where子句只能對沒有分組統計錢的數據行進行篩選。怎麼辦?Having子句,用來對分組後的數據進行篩選,將“組”看作“列”
  • 要求3:統計分數大於60分的,不同班級的,男生和女生的總分數,並按照總分數降序排列
--使用having子句進行分組篩選
--要求1:統計不同班級的學生總分數
select Class_id,sum(score) as 總分數 from Student group by Class_id;
--要求2:查詢班級總分數超過200的班級?思考能否使用where?會報錯因爲where子句只能對沒有分組統計錢的數據行進行篩選。怎麼辦?Having子句,用來對分組後的數據進行篩選,將“組”看作“列”。
select Class_id,sum(score) as 總分數 from Student 
group by Class_id 
having sum(score)>200;

--要求3:統計分數大於60分的,不同班級的,男生和女生的總分數,並按照總分數降序排列
select sex,Class_id, sum(score) as 總分數 
from Student 
where score>=60 
group by sex,Class_id
order by sum(score);

注意:where和having子句可以在同一個select語句中一起使用,但是要注意使用順序

 

4、多表連接查詢

截止到前面我們進行的所有查詢,都是基於單個表格所進行的查詢。

要求1:查詢班級編號爲1的學生

select * from Student where Class_id=1;

       比如我們查詢學生信息的時候無法看到學生班級信息,因爲班級信息存儲在另外一個表格中。那像這種需要從2個以上的表中選擇或者比較數據的時候,就需要使用多表連接查詢。

多表連接查詢:select * from Student,Class where Student.Class_id=Class.id;

--多表查詢準備工作,創建班級表和學生表,並分別插入數據
create table banji(
	id int primary key ,
	banji_name varchar(10)
	);
insert into banji (id,banji_name)
select 1,1831308 union
select 2,1831309 union
select 3,1831310 union
select 4,1831311;
--創建學生表
create table stu(
	id int primary key,
	names varchar(5) not null,
	banji_id int not null
	);
insert into stu(id,names,banji_id)
select 1,'張三',1 union
select 2,'李四',1 union
select 3,'王五',2 union
select 4,'趙六',3 union
select 5,'錢七',1 union
select 6,'孫九',9 union
select 7,'田十',8 

 

4.1 多表連接查詢方式:

  • 全連接(交叉連接):也稱笛卡爾集,是將兩個表中的每一條數據都進行組合。
  • 內連接(自然連接、條件連接):它是根據兩個或多個表中的列之間的關係,從這些表中查詢數據。特別是兩個表存在主外鍵關係時,通常使用內連接查詢。這也是常用典型的連接查詢。(where、inner join)
  • 外連接(左連接、右連接):外連接查詢至少返回一個表中的所有記錄,根據匹配條件有選擇性地返回另一張表的記錄。外連接可以是左外連接(left join)、右外連接(right join)
--多表查詢準備工作,創建班級表和學生表,並分別插入數據
create table banji(
	id int primary key ,
	banji_name varchar(10)
	);
insert into banji (id,banji_name)
select 1,1831308 union
select 2,1831309 union
select 3,1831310 union
select 4,1831311;
--創建學生表
create table stu(
	id int primary key,
	names varchar(5) not null,
	banji_id int not null
	);
insert into stu(id,names,banji_id)
select 1,'張三',1 union
select 2,'李四',1 union
select 3,'王五',2 union
select 4,'趙六',3 union
select 5,'錢七',1 union
select 6,'孫九',9 union
select 7,'田十',8 


全連接:表1*表2,表1的每一行分別和表2的每一行匹配,會有4*7=28條記錄集。

內連接:表1的id列和表2的banji_id列相等的,會有5條記錄集。

左連接:左表(表1)爲主,拿左表進行匹配,值相等的都提取,缺少的以空值提取,會有6條記錄集。

右連接:右表(表2)爲主,拿右表進行匹配,值相等的都提取,缺少的以空值提取,會有7條記錄集。

 

4.2  全連接查詢

語法:select  列名列表  from  表1 ,  表2 ;

適用場景:比如有學生表、課程表,如果有考試表,且要求每個學生每門課程都要有成績,這樣就需要將select * from 學生表,課程表 的結果插入到考試表裏。

注意:全連接用的較少,一般在後面加上where子句,也就是內連接。

 

4.3 左連接查詢

又稱左向外連接,查詢的結果集包括SQL語句中左表的所有行,右表中匹配的行。如果左表的某行在右表中沒有匹配行,則用空值表示。

語法:select  列名列表  From  表1  left   join   表2  on  (表1.列=表2.列) ;

注意:此語法中,表1是主表

 

4.4 右連接查詢

右向外連接,查詢的結果集包括SQL語句中右表的所有行,左表中匹配的行。如果右表的某行在左表中沒有匹配的行,則用空值表示

語法:select  列名列表  From  表1  right   join   表2  on  (表1.列=表2.列) ;

注意:此語法中,表2是主表

 

4.5 內連接查詢

        使用比較運算符(包括=、>、<、<>、>=、<=、!>和!<)進行表間的比較操作,查詢與連接條件相匹配的數據。根據比較運算符不同,內連接分爲等值連接和不等連接兩種。

4.5.1   等值連接

     概念:在連接條件中使用等於號(=)運算符,其查詢結果中列出被連接表中的所有列,包括其中的重複列。

 

4.5.2  不等連接

   概念:在連接條件中使用除等於號之外運算符(>、<、<>、>=、<=、!>和!<)

 

注意:

  • 在進行多表連接查詢時,我們可以給表指定別名,用以簡化代碼。
  • 列名,一般會通過表名.列名來進行指定。如果查詢的列名在不同表中不重複,則對該列的引用可以不用表名進行限定。

 

練習:

--查詢Class表和Student表,查詢班級是1的學生信息

--查詢Class表和Student表,查詢班級是1的,且成績大於60分的學生信息

--查詢Class表和Student表,查詢班級是1的學生信息
--使用where
select c.class,c.id,s.Names,s.Score
from Class as c ,Student as s
where c.id=s.Class_id and c.id=1;
--使用inner join
select c.id,c.class,s.Names,s.Score
from Class c  inner join  Student s
on c.id=s.Class_id
where c.id=1;

--查詢Class表和Student表,查詢班級是1的,且成績大於60分的學生信息
select c.class,c.id,s.Names,s.Score
from Class as c ,Student as s
where c.id=s.Class_id and c.id=1 and s.Score>60;

select c.id,c.class,s.Names,s.Score
from Class c  inner join  Student s
on c.id=s.Class_id
where c.id=1 and s.Score>60;

 

本案例完整代碼:

--創建數據庫StudentDB
create database StudentDB;
--使用數據庫
use StudentDB;
--創建表:班級表(編號、班級、人數)
create table Class(
	id int primary key,              --編號      整數 主鍵
	class char(20) unique not null,  --班級      字符 唯一鍵 非空 
	stu_numbers int not null         --班級人數  整數  非空
);
--向班級表中插入數據
insert into Class(id,class,stu_numbers)
select 1,'1831308',52 union
select 2,'1831309',48 union
select 3,'1831310',47 union
select 4,'1831311',44
--創建學生表(從表,班級列引用主表的主鍵)
create table Student(
	Id int primary key,                  --編號 整數 主鍵
	Class_id int references Class(id),   --班級 整數 外鍵(引用班級表class裏的主鍵id)
	SchoolNumber int unique not null,    --學號 整數 唯一鍵
	Names nvarchar(30) not null,         --姓名 字符 非空
	Age int,                             --年齡 整數
	Sex char(2),                         --性別 字符
	Score float                          --分數 浮點數
);
--向學生表中插入數據
insert into Student(Id,Class_id,SchoolNumber,Names,Age,Sex,Score)
select 1,2,1001,'張傑',18,'男',78.5 union
select 2,1,1002,'謝娜',19,'女',58 union
select 3,1,1003,'李連杰',22,'男',89 union
select 4,3,1004,'張揚',21,'男',90 union
select 5,2,1005,'歐娜娜',18,'女',60 union
select 6,4,1006,'關曉彤',21,'女',87 union
select 7,1,1007,'李易峯',22,'男',73 union
select 8,3,1008,'關彤彤',23,'女',93 union
select 9,1,1009,'李四',17,'男',69 union
select 10,4,1010,'張三',18,'女',88.5


--使用group by進行分組查詢
--要求1:查詢school數據庫中表student中的總分數
select sum(Score) as 總分數 from Student;
--要求2:統計男生和女生的總分數如何進行?思考:先按照性別進行男生女生分組,然後再利用sum()函數進行求和。
select Sex 性別,sum(Score) 總分數 from Student group by Sex;
--要求3:統計不同年級,男生和女生的總分數,並且按照總分數從高往低進行排序如何進行?思考:先按照年級和性別分組,然後再利用sum()函數進行求和,最後按照求和結果進行降序排列。
select Sex,Class_id, sum(score) as 總分數 from Student 
group by Sex, Class_id 
order by sum(score) desc;


--使用having子句進行分組篩選
--要求1:統計不同班級的學生總分數
select Class_id,sum(score) as 總分數 from Student group by Class_id;
--要求2:查詢班級總分數超過200的班級?思考能否使用where?會報錯因爲where子句只能對沒有分組統計錢的數據行進行篩選。怎麼辦?Having子句,用來對分組後的數據進行篩選,將“組”看作“列”。
select Class_id,sum(score) as 總分數 from Student 
group by Class_id 
having sum(score)>200;

--要求3:統計分數大於60分的,不同班級的,男生和女生的總分數,並按照總分數降序排列
select sex,Class_id, sum(score) as 總分數 
from Student 
where score>=60 
group by sex,Class_id
order by sum(score);

--多表查詢準備工作,創建班級表和學生表,並分別插入數據
create table banji(
	id int primary key ,
	banji_name varchar(10)
	);
insert into banji (id,banji_name)
select 1,1831308 union
select 2,1831309 union
select 3,1831310 union
select 4,1831311;
--創建學生表
create table stu(
	id int primary key,
	names varchar(5) not null,
	banji_id int not null
	);
insert into stu(id,names,banji_id)
select 1,'張三',1 union
select 2,'李四',1 union
select 3,'王五',2 union
select 4,'趙六',3 union
select 5,'錢七',1 union
select 6,'孫九',9 union
select 7,'田十',8 

--全連接查詢
select * from banji,stu;

--左連接查詢
select * from banji left join stu on (banji.id=stu.banji_id);

--右連接查詢
select * from banji right join stu on (banji.id=stu.banji_id);


--內連接查詢 ineer join
--通常使用“=”或者“<>”等比較運算符來判斷兩列數據值是否相等。
--等值連接
select * from banji inner join stu on banji.id=stu.banji_id;

--不等連接
select * from banji inner join stu on banji.id <> stu.banji_id;



--查詢Class表和Student表,查詢班級是1的學生信息
--使用where
select c.class,c.id,s.Names,s.Score
from Class as c ,Student as s
where c.id=s.Class_id and c.id=1;
--使用inner join
select c.id,c.class,s.Names,s.Score
from Class c  inner join  Student s
on c.id=s.Class_id
where c.id=1;

--查詢Class表和Student表,查詢班級是1的,且成績大於60分的學生信息
select c.class,c.id,s.Names,s.Score
from Class as c ,Student as s
where c.id=s.Class_id and c.id=1 and s.Score>60;

select c.id,c.class,s.Names,s.Score
from Class c  inner join  Student s
on c.id=s.Class_id
where c.id=1 and s.Score>60;

 

 

 

 

 

 

=======================這裏是結束分割線=======================

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章