【mysql練習二】實踐導向的從淺入深全面複習SQL語言和一些SQL關鍵字練習(學練結合版)

複習SQL語句:

1.建立數據庫 create database:

create database test;

2.切換使用數據庫 use:

use test;

3.如果有報錯,看下warnings show:

 show warning;

在這裏插入圖片描述

4.建立表如下 create table:

後面加defalut就初始化了默認值,否則爲null(無)。注意無不是空格‘ ’ 看下圖的表結構可以看出區別

CREATE TABLE test1
(
PersonID int default 0,
LastName varchar(255) default '',
FirstName varchar(255),
Address varchar(255),
City varchar(255)
);

5.查看錶結構 describe:

注意紅線處表示了有無default的區別

describe test1;

在這裏插入圖片描述

6.刪除表 drop table:

drop table test1;

7.刪除數據庫 drop dataset:

drop database test;

8.插入行數據 insert into:

方法1:

insert into test1 
values('11603009','Lucy','Cheng','JingAn Street','ShangHai');

方法2:

insert into test1(PersonID,LastName ,FirstName ,Address,City  ) 
values('11603007','Candy','Lu','NanShan  Street','ShenZhen');

可以打亂結構順序:

insert into test1(FirstName ,Address,City,PersonID,LastName )
values('JingAn Street','ShangHai','11603009','Lucy','Cheng');

在指定的列插入數據,其他留空:

insert into test1(LastName ,FirstName ) 
values('Admin','Admin');

9.查看目前表裏全部數據 select from:

select * from test1;

在這裏插入圖片描述

10.刪除重複元素,保留order_id最小的元素:

1.找出哪些元素重複的需要刪除:

例如此處id相同的就算重複,但是其他相同都不算重複,此時就按照id進行分組:
利用了關鍵詞groupby

select PersonID, count(*) from test1 GROUP BY PersonID;

可以看到按照id分組了:
在這裏插入圖片描述

2.重複行的組大小大於1。使用HAVING子句只顯示重複行:
select PersonID, count(*) from test1 GROUP BY PersonID having count(*)>1;

得到:
在這裏插入圖片描述

解惑:
1.爲什麼不能使用WHERE子句?

因爲WHERE子句過濾的是分組之前的行,HAVING子句過濾的是分組之後的行
這裏的含義和執行順序是:
按照personID分組,相同的分爲一組,並計算出每個分組的數量,並且選擇出count(*)大於1的組,最後選出PersonID和count(*)展示出結果。
執行順序從後往前:
先執行GROUP BY PersonID,再執行:having count(*)>1,最後執行:select PersonID, count(*) from test1

3.刪除重複行:

一種簡單的方法是建立一個臨時表,記錄下需要刪除的重複元素,只保留一個:
如果行完全一樣,刪除哪個就都無所謂了,這樣就沒什麼意義了,而且選擇的時候也不好進行選擇,所以我們增加一個自增的主索引,達到區分每一行的目的:
查看當前表的索引:

 show index from test1;

可以看到爲空:
在這裏插入圖片描述
設置一個int類型的自增的主鍵( primary key):

 alter table test1 add order_id int auto_increment primary key;

關鍵字alter可以插入列,自增索引必須是int類型。
再查看一下,可以看到主鍵的信息
在這裏插入圖片描述
注意主鍵不是index不能只刪除索引,只能連着刪除字段了。

alter table test1 drop order_id;

關於索引,主鍵和字段的區別,在mysql練習一的概念區有講,這裏不重複了。
現在查看一下表:
在這裏插入圖片描述
於是只保留order_id最小的那個值:

select PersonID , MIN(order_id),count(*) from test1 group by PersonID having count(*) > 1;

在這裏插入圖片描述
建立一個臨時表:

create temporary table to_delete (PersonID int not null, min_id int not null); 

只保留order_id最小的那個值,所以先保存最小的order_id:

insert into to_delete(PersonID , min_id)  
  select PersonID , MIN(order_id) from test1 group by PersonID having count(*) > 1;

聯合對比兩個表,並且進行刪除:

delete from test1 
  where exists(  
     select * from to_delete
     where to_delete.PersonID  = test1.PersonID and test1.order_id<>to_delete.min_id
  );

結果:
在這裏插入圖片描述

11.不能重複插入unique:

上面的表費了很大的力氣去解決重複的問題,如果在插入的時候,就能檢查出錯誤,那就省了很多時間和功夫。
所以這是數據庫設計師的鍋,設計的時候就該設計好:
創建帶有主鍵和索引的表: 主鍵就限制不能重複了,索引是便於查找用的,有很多種索引,不同引擎用的底層算法也不一樣。另外有些值不能爲空,否則後續容易出錯,這就要設置not NULL條件了。約束字段爲自動增長,被約束的字段必須同時被key約束

CREATE TABLE test2
(
order_id int auto_increment primary key,
PersonID int default 0,
LastName varchar(255) default '' not null,
FirstName varchar(255)default '' not null,
Address varchar(255) not null,
City varchar(255) not null
);

這樣設置之後,order_id每加上1就會索引自增1,
而且如果插入的數據缺少一些關鍵項,就會失敗:
在這裏插入圖片描述
插入沒有default的值,而又沒有定義這個值,就會報錯了。

insert into test2(LastName ,FirstName ) values('Admin','Admin');

在這裏插入圖片描述
而有default的值或者可以爲null的值的話,就可以插入了

insert into test2(Address ,City) values('Tomorrow Road','Admin');

在這裏插入圖片描述

12. 加唯一限制條件的索引和外鍵

mysql> alter table 表名 add unique 索引名 (字段名);
例如:

alter table test1 add unique PersonID_index(PersonID);

查看一下效果:這樣一來personID就唯一了。
在這裏插入圖片描述
嘗試插入默認值失敗了,因爲personID 0已經被佔用。
在這裏插入圖片描述
當然這裏建表時的限制條件還可以加,例如:

create table test3
(
order_id int auto_increment primary key,   # int類型的自增主鍵
PersonID int default 0,   # 默認爲0
Class varchar(255) default '' not null,  # 非空默認爲‘’
InSchoolDay datetime DEFAULT CURRENT_TIMESTAMP,  # 默認值爲當前插入時間
foreign key(PersonID ) references test1(PersonID          #自己表中的PersonID 關聯到test1中的PersonID,如果test1裏沒有personID就不能進行插入了
on update cascade              #更新同步外鍵foreign key的PersonID
on delete cascade ,              #刪除同步外鍵foreign key到PersonID
#這樣一來,test1裏和test3的條目就會同步刪除和更新了
ChangeTime datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP# 默認值爲當前插入時間和更改時間
);

無註釋語句如下:

create table test4(
order_id int auto_increment primary key,
PersonID int default 0,
Class varchar(255) default '' not null,
InSchoolDay datetime default current_timestamp,
foreign key(PersonID) references test1(PersonID) on update cascade on delete cascade,
ChangeTime datetime default current_timestamp on update current_timestamp);

另外還可以加上check條件和constraint約束:

constraint  check (City='ShenZhen' or 'ShangHai' or 'BeiJing')
注意:MySQL 所有的存儲引擎都不支持 CHECK和constraint 約束,僅可用於Oracle

MySQL中可以寫 CHECK 約束,但會忽略它的作用,因此 CHECK 並不起作用,因此實現對數據約束有兩種方法:

  1. 在 MySQL 中約束,如使用 ENUM 類型 或者 觸發器
  2. 在應用程序裏面對數據進行檢查再插入。

查看錶:describe test3;
在這裏插入圖片描述
根據表1裏的personID試着插入一條:

insert into test3(PersonID ,Class )
values('11603009','Class One');

在這裏插入圖片描述
成功了!
如果表1裏沒這個人的id就會發生插入失敗:
在這裏插入圖片描述
說到這裏,應該明白了,外鍵就是放在另一個表的主鍵,
如果關聯的那個表裏沒有這個項就會發生插入失敗。如果有,才能正常插入;

insert into test3(PersonID ,Class )values('11603109','Class One');

得到兩個項:
在這裏插入圖片描述
那麼如果刪除會發生什麼呢?我們先對test1進行刪除:

delete from test1 
where PersonID='11603009';

在這裏插入圖片描述
可以看到,不僅test1裏的內容被刪除了,test3裏的內容也沒有了。
在這裏插入圖片描述
如果對test3進行刪除:

delete from test3 
where PersonID='11603007' and Class='Class Two';

可以看到,test1沒有受到任何影響,而test3裏的行被刪除了。
在這裏插入圖片描述
如果沒有對外鍵設置on update cascade和on delete cascade的話,數據庫會簡單地報錯,而不是同步刪除!
在這裏插入圖片描述

解惑:從約束角度看primary key字段的值不爲空且唯一,那我們直接使用not null+unique不就可以了嗎,要它幹什麼?

主鍵primary key是innodb存儲引擎組織數據的依據,innodb稱之爲索引組織表,一張表中必須有且只有一個主鍵。
一個表中可以:

  1. 單列做主鍵
  2. 多列做主鍵(複合主鍵)

但凡創建表,我們就要注意啦:

1.必須有且只要一個主鍵
2.通常id字段被設置爲主鍵

13.更新update set 和簡單排序order by

update test1 
set LastName='July',Address='Friend Road',PersonID='11603008',City='ShangHai',FirstName='Click' 
where LastName='Admin' and FirstName='Admin';

在這裏插入圖片描述
test3插入兩條

insert into test3(PersonID ,Class )values('11603007','Class One');
insert into test3(PersonID ,Class )values('11603006','Class Two');

更新test1裏July的學號:

update test1 
set PersonID='11603008' 
where LastName='July';

在這裏插入圖片描述
注意,不能在test3裏進行更新,因爲PersonId是外鍵:
在這裏插入圖片描述
多在test1裏插入幾條信息:

insert into test1(PersonID,LastName ,FirstName ,Address,City  ) 
values('11603009','Lucy','Cheng','JingAn Street','ShangHai');
insert into test1(PersonID,LastName ,FirstName ,Address,City  ) 
values('11603010','Andy','Meng','HePing Road','BeiJing');
insert into test1(PersonID,LastName ,FirstName ,Address,City  )  
values('11603011','Mark','Lu','JingAn Street','ShangHai');
insert into test1(PersonID,LastName ,FirstName ,Address,City  )  
values('11603014','Ken','Wang','Merry Street','ShenZhen');

對姓氏進行排序:

select * from test1 
order by FirstName;

在這裏插入圖片描述

14.別名用as:

把查找到的PersonId改叫studentID:

select PersonID as StudentID from test1;

這在做內連接inner join或者是用in關鍵字時很有效,不會弄錯。
在這裏插入圖片描述
而表的改名則利於縮短拼寫,例如test1縮寫爲t1,test2縮寫爲t2,
則如果要查找來自上海的同學的地址和班級,則有:

select t1.Address,t2.Class 
from 
test1 as t1,
test3 as t2 
where t1.PersonID=t2.PersonID and City= 'ShangHai';

在這裏插入圖片描述
也可以用in的語句來代替:(請嘗試一下自己寫!)
我得到了下面的結果:

select Address,Class 
from test1 join test3 
where test1.PersonID 
in (select test1.PersonID 
from test1 
where City='ShangHai');






請思考一下這樣會得到什麼樣的結果!!!!!!!!!





這樣寫出來的是錯的,得到的是兩個表全連接後的結果:
在這裏插入圖片描述
IN 操作符允許您在 WHERE 子句中規定多個值。
等價於多個‘=’的或的和,而上面的例子裏可以看到,得到了三個PersonID滿足條件:
在這裏插入圖片描述
而Class信息在表test3,Address信息在test1,
如果使用語句

select Address,Class from test1,test3;

就得到了了36個條目,
在這裏插入圖片描述
所以正確的寫法如下:

select Address,Class 
from test1,test3 
where test1.PersonID =test3.PersonID 
and test1.PersonID 
in (select test1.PersonID from test1 where City='ShangHai');

首先限制了test1.PersonID=test3.PersonID,這樣就濾去了兩個表相乘或者說全連接得到的多餘的不合法項,因爲personID是兩個表共有的而且是主鍵外鍵關係。
在這裏插入圖片描述
有些語句是多種寫法可以相互替換的,有些則是不可以的,有些替換起來很麻煩,不過條條大路通羅馬。
這個還可以用inner join內連接或者join(他們等價)來寫:

select Address,Class 
from test1 
inner join test3 
on test1.PersonID=test3.PersonID and  City='ShangHai';

得到結果:
在這裏插入圖片描述

解惑:關於join用on還是用where的區別:

在使用 join 時,on 和 where 條件的區別如下:

  1. on 條件是在生成臨時表時使用的條件,它不管 on 中的條件是否爲真,都會返回左邊表中的記錄。
  2. where 條件是在臨時表生成好後,再對臨時表進行過濾的條件。這時已經沒有 left join 的含義(必須返回左邊表的記錄)了,條件不爲真的就全部過濾掉。
    參考網址: 在使用 join 時,on 和 where 條件的區別
結論:

full 則具有 left 和 right 的特性的並集。 而 inner join 沒這個特殊性,則條件放在 on 中和 where 中,返回的結果集是相同的

15.聯合 Union

當兩個表中有相同含義的項時,UNION 操作符用於合併兩個或多個 SELECT 語句的結果集。
請注意,UNION 內部的每個 SELECT 語句必須擁有相同數量的列。列也必須擁有相似的數據類型。同時,每個 SELECT 語句中的列的順序必須相同。
union不含重複,union all則含有重複。
舉個簡單的例子:

select PersonID from test1 
union 
select PersonID from test3;

在這裏插入圖片描述
而union all含有重複項:
在這裏插入圖片描述
此處舉個不恰當的例子:
說明了只要數據類型相同,就可以union
在這裏插入圖片描述

16.複製表 insert into… select from

刪除表2的多餘內容:

delete from test2 where order_id>2;

進行復制插入:

insert into test2(PersonID,LastName,FirstName,Address,City,order_id) 
select * from test1 
where order_id >4;

在這裏插入圖片描述

17.創建索引:create index

create index 語句用於在表中創建索引。
在不讀取整個表的情況下,索引使數據庫應用程序可以更快地查找數據。在表中創建索引,以便更加快速高效地查詢數據。用戶無法看到索引,它們只能被用來加速搜索/查詢。
註釋:更新一個包含索引的表需要比更新一個沒有索引的表花費更多的時間,這是由於索引本身也需要更新。因此,理想的做法是僅僅在常常被搜索的列(以及表)上面創建索引。

 create unique index pid_index on test1(PersonID);
 create index pid_index2 on test1(PersonID);

創建unique索引出現了warnings,可以看到:
在這裏插入圖片描述
可能是因爲這個項不是主鍵而且也沒有設置unique屬性。

show index from test1;

可以看到當前表的索引(主鍵自身就是一個默認的索引)
在這裏插入圖片描述

18.視圖View:視圖相當於將查詢進行封裝

在 SQL 中,視圖是基於 SQL 語句的結果集的可視化的表。視圖包含行和列,就像一個真實的表。視圖中的字段就是來自一個或多個數據庫中的真實的表中的字段。可以向視圖添加 SQL 函數、WHERE 以及 JOIN 語句,也可以呈現數據,就像這些數據來自於某個單一的表一樣。
可以想象視圖是一個巨大的表的某些列和某些行,是原表的縮小版,更改原表,視圖裏的信息也變了

對深圳人的姓名創建一個視圖並查看:

create view name_view 
as select FirstName,LastName 
from test1 where City='ShenZhen';

在這裏插入圖片描述

19.使用 ENUM 類型 或者 觸發器

單獨開一個講這兩個:
傳送連接:【mysql練習三】使用 ENUM 類型 或者 觸發器

自測:

自測題1:

有test1和test3表如下:
在這裏插入圖片描述
在這裏插入圖片描述
在test1中對深圳或者上海人的LastName排序,只顯示LastName和城市信息:
(自己輸入一下語句做做練習吧!)
答案查看目錄答案1
提示:order by 、or、 select

自測題2:

查看test1表中共有哪幾個城市,不要顯示重複城市:
提示:distinct

自測題3:

查看test1表中每個城市有多少人:
提示:group bycount()

自測題4:

先往test3裏插入四條信息:

insert into test3(PersonID ,Class )values('11603009','Class One');
insert into test3(PersonID ,Class )values('11603010','Class One');
insert into test3(PersonID ,Class )values('11603014','Class One');
insert into test3(PersonID ,Class )values('11603011','Class Two');

查看最先入學的人的班級.
提示:可以有多種方法,但是他們的複雜度可能不一樣

自測題5:

查找居住地含有‘Street’的人的姓名:
提示:like

自測題6:

查找名稱首字母不以A-C開頭的人的LastName:
提示:regexp

自測題7:

查找班級爲Class One的所有人的名字:
提示:IN 與 = 的異同
相同點: 均在WHERE中使用作爲篩選條件之一、均是等於的含義
不同點: IN可以規定多個值,等於規定一個值
這裏有多種解法,可以用in也可以用join

自測題8:

查找入學日期在2020年4月2日18:00到18:30的不是北京和廣東的學生的LastName和FirstName:
提示:not inbetween and

自測題9:

下面有學生的各科分數表grade:

create table grade(
order_id int auto_increment primary key,
PersonID int default 0,
Math int default 0,
Chinese int default 0,
English int default 0,
Physics int default 0,
foreign key(PersonID) references test1(PersonID) on update cascade on delete cascade
);

insert into grade(PersonID,Math,Chinese,English,Physics) values('11603009',120,118,138,50);
insert into grade(PersonID,Math,Chinese,English,Physics) values('11603007',110,106,114,73);
insert into grade(PersonID,Math,Chinese,English,Physics) values('11603008',90,98,148,82);
insert into grade(PersonID,Math,Chinese,English,Physics) values('11603010',125,111,126,55);
insert into grade(PersonID,Math,Chinese,English,Physics) values('11603011',98,123,121,92);
insert into grade(PersonID,Math,Chinese,English,Physics) values('11603014',104,131,116,75);

1.查詢年級各科目平均分,
2.查找各科最高分的同學的名字(FirstName+LastName)
3.查詢各個同學的總分,並按照學號排序
4.查找每個班級有一或者科目不及格(語文數學英語<90,物理小於60)的不及格人數
5.對班級1的同學的成績建立視圖,計算班級平均分和最高分,創建視圖,求均值和最大值分開寫成三句。
6.查看總分大於430的同學所在的班級號,如果沒有這個同學,輸出空

答案:

答案1:
select LastName,City  # 只要LastName和城市信息:
from test1 # 從表test1選擇
where City='ShangHai'or City='ShenZhen' # 只要深圳或者上海人
order by LastName; # 按照LastName排序

得到:
在這裏插入圖片描述

答案2:
 select distinct city 
 from test1;

得到
在這裏插入圖片描述

答案3:
select count(*),city 
from test1 
group by city;

得到
在這裏插入圖片描述

答案4:
1.利用min()函數查找,複雜度1
select class,min(InSchoolDay) from test3 ;

不過這樣就少了一條,因爲有兩個人同時入學了。
在這裏插入圖片描述

2.先排序再取最前的幾個值(複雜度:排序+選擇 = o(nlogn))
select class,InSchoolDay 
from test3 
order by InSchoolDay 
limit 1;

在這裏插入圖片描述
注意: 當表過大或者是有很多條目的時候,如果只需要前面的幾條,可以用關鍵字limit來限制數量。

3.目前想到的最優解
 select class,inschoolday 
 from test3 
 where inschoolday 
 in(select min(inschoolday) 
 from test3);

先利用子查詢:select min(inschoolday) from test3
得到了最小的入學日期集合{ 2020-04-02 18:24:50}:,然後對test3中入學日期在這個最小入學日期的集合(這個集合只有一個數)中的日期全部選出,然後顯示班級和日期,可以看到效果如下:
在這裏插入圖片描述

答案5:
select FirstName,LastName 
from test1 
where address 
like '%Street%';

like關鍵字+%通配符

% 替代 0 個或多個字符
_ 替代一個字符
^或者! 不在字符列中的任何單一字符

在這裏插入圖片描述

答案6:
select * from test1 where LastName regexp '^[^A-C]';

在這裏插入圖片描述
如果題目是LastName可以是A-C:
在這裏插入圖片描述
regexp是正則表達式的意思,後面的^[A-C]表示^是正則表達式開頭符號,[A-C]表示可以是A、B、C,
關於正則這裏不多敘述,可以看這個:正則表達式符號手冊

答案7:
select FirstName,LastName 
from test1 
where PersonID 
in(select PersonID 
from test3 
where Class='Class one');

這裏要使用兩個表連查,首先從test3表裏找出滿足班級是Class One的人的學號組,然後再從test1中找滿足學號相等的全部的組。
在這裏插入圖片描述

或者可以直接用join:

select FirstName,LastName 
from test1 
inner join test3 
on test1.PersonID=test3.PersonID 
and Class='Class One' 
order by FirstName;

這裏我對FirstName進行了一下排序方便看
在這裏插入圖片描述
SQL JOIN 子句用於把來自兩個或多個表的行結合起來,基於這些表之間的共同字段。
最常見的 JOIN 類型:SQL INNER JOIN(簡單的 JOIN)。 SQL INNER JOIN 從多個表中返回滿足 JOIN 條件的所有行。

Join類型 含義
INNER JOIN 如果表中有至少一個匹配,則返回行
LEFT JOIN 即使右表中沒有匹配,也從左表返回所有的行
RIGHT JOIN 即使左表中沒有匹配,也從右表返回所有的行
FULL JOIN 只要其中一個表中存在匹配,則返回行

可以看到,左連接返回了全部左表(test1)裏的值,右連接返回了全部右表(test3)裏的值,由於左表中有兩行不匹配,所以多出了兩行NULL。
外連接就好像是爲非基準表添加了一行全爲空值的萬能行,用來與基準表中找不到匹配的行進行匹配。假設兩個沒有空值的表進行左連接,左表是基準表,左表的所有行都出現在結果中,右表則可能因爲無法與基準表匹配而出現是空值的字段。
在這裏插入圖片描述
而全連接呢?mysql是不支持full join的,但仍然可以同過左外連接+ union+右外連接實現,不知道8.01版本是否有做實現。
測試了一下感覺好像是‘乘’的效果
在這裏插入圖片描述

答案8:
select LastName,FirstName 
from test1,test3 
where test1.PersonID=test3.PersonID and 
InSchoolDay between '2020-04-02 18:00:00' 
and '2020-04-02 18:30:00' 
and City not in ('BeiJing','GuangDong');

得到結果:
在這裏插入圖片描述

答案9:

1.查詢年級各科目平均分:

select avg(Math), avg(Chinese), avg(English), avg(Physics) 
from grade;

在這裏插入圖片描述
2.查找各科最高分的同學的名字(FirstName+LastName)
方法一:

select FirstName,LastName from test1 where personID 
in (select personID from grade where Math =( select max(Math) from grade) 
union select personID from grade where Chinese =( select max(Chinese)  from grade) 
union select personID from grade where English =( select max(English)  from grade) 
union select personID from grade where Physics =( select max(Physics)  from grade) );

利用select personID from grade where Math =( select max(Math) from grade語句聯合得到四個科目的最高分的同學的ID,然後再利用PersonID在test1單個表裏查名字。
在這裏插入圖片描述

拓展:
1.如果想查詢各科最高分的同學的學號和該科成績max_grade,應該如何查詢呢?

select personID,max(Math) 
as max_grade from grade where Math in( select max(Math) from grade) 
union select personID,max(Chinese) as max_grade from grade where Chinese in( select max(Chinese) from grade) 
union select personID,max(English) as max_grade from grade where English in( select max(English) from grade) 
union select personID,max(Physics) as max_grade from grade where Physics in( select max(Physics) from grade)

在這裏插入圖片描述
2.如果想查詢各科最高分的同學的名字和該科成績,如何查詢?

select FirstName,LastName,max_grade from(
select personID,max(Math) as max_grade from grade where Math in( select max(Math) from grade) 
union select personID,max(Chinese) as max_grade from grade where Chinese in( select max(Chinese) from grade) 
union select personID,max(English) as max_grade from grade where English in( select max(English) from grade) 
union select personID,max(Physics) as max_grade from grade where Physics in( select max(Physics) from grade)) 
as max_table,test1 
where test1.PersonID=max_table.personID;

結果:
在這裏插入圖片描述
其實思路是一樣的:先得到四個最高分者的PersonID和最高分,把最高分數的結果重命名爲max_grade,得到一個表命名爲max_table然後和test1表聯合,就得到了結果。
max_table:
在這裏插入圖片描述

3.查詢各個同學的總分,並按照學號排序:

select PersonID,Math+Chinese+Physics+English 
from grade 
order by PersonID;

在這裏插入圖片描述
注意:sum()是對列做加法,不是對行!!
4.查找每個班級有一或者科目不及格(語文數學英語<90,物理小於60)的不及格人數

select count(*),class 
from test3,grade 
where grade.PersonId=test3.personID 
and (Math<90 or Chinese<90 or Physics<60 or English<90) 
group by Class;

在這裏插入圖片描述
拓展:
查找每個班級沒達到優秀的科目數(語文數學英語<120,物理小於80)

select class,count(*) from 
(select personID from grade where Chinese<120 
union all select personID from grade where English<120 
union all select personID from grade where Math<120 
union all select personID from grade where Physics<90) 
as grade_id,test3 
where test3.PersonID=grade_id.PersonID 
group by class; 

聯合union alll全部的滿足條件的id,然後按照班級進行分組group by
注意不要用union,因爲會排除重複。
在這裏插入圖片描述

5.對班級1的同學的成績建立視圖,計算班級平均分和最高分:

create view class_one 
as select grade.PersonID, Math,Chinese,English,Physics 
from grade,test3 
where test3.PersonID=grade.PersonID and Class='Class One';

在這裏插入圖片描述
計算平均值和最大值:

select avg(Math),avg(Chinese),avg(English),Avg(Physics) from class_one;
select max(Math),max(Chinese),max(English),max(Physics) from class_one;

在這裏插入圖片描述
6.查看總分大於430的同學所在的班級號,如果沒有這個同學,輸出空

select FirstName,LastName 
from test1 where 
Exists (select PersonID 
from grade where Math+Chinese+English+Physics>430 
and test1.PersonID=grade.PersonID );

在這裏插入圖片描述

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