1.前言
太久沒有在數據庫做一些復雜的sql了,基本上將數據庫的查詢邏輯全放在了Java里做,
一來呢,可以減輕數據庫的負擔,二來呢,在java寫,邏輯感會更強,數據類型更豐富也容易操作。
然而。。。面試卻喜歡靠復雜的sql ,好吧,即便我不想,但復習一波還是免不了的。
常用的關系型數據庫有 MySQL和Oracle 。Oracle 比較喜歡使用存儲過程做業務 ,當然,MySQL也可以,但是沒怎么用,
自從工程使用mybatis框架,就不再使用存儲過程了,業務基本是增刪改查,查詢數據的邏輯都是從數據庫取相應數據出來后用Java計算,
再從數據庫獲取最終想要的數據,本來是本着減輕數據庫負擔才這樣做的,並發操作會用上積極鎖【樂觀鎖】,因此也就不需要擔心 臟數據問題。
MySQL和Oracle的語法部分是不同的,有時候用着MySQL,寫着寫着就用上了Oracle的語法,還一臉懵逼的查了半天到底哪里錯,不常使用的東西就是容易忘。
總結: (1)Oracle 使用nvl() 函數,MySQL使用 ifnull() 函數 來對數據進行判斷是否為空, 如果是空則使用替代的數據 ,參數一樣 ,如if(x.age,0),意思是如果年齡字段為空則 輸出 0 . (2)sum()函數是運算函數,允許 加減乘除計算 ,如果要使用,則必須使用 group by 分組 ,限定好分組 sum獲取的計算數據才不會錯,否則將會導致全表計算在一起。 (3)avg()函數是計算平均數的,用法根據需要與 group by 分組配合使用, 如果是計算全表某字段的平均分,則不要使用。
(4)having 關鍵字可以篩選分組后的各組數據,也就是說可對分組完成后的數據做邏輯條件判斷 ,與where類似,但是where無法這樣使用,因為where關鍵字無法與聚合函數一起使用
2.復習題
數據庫源碼

/* Navicat MySQL Data Transfer Source Server : cen Source Server Version : 50528 Source Host : localhost:3306 Source Database : kktest Target Server Type : MYSQL Target Server Version : 50528 File Encoding : 65001 Date: 2020-06-17 08:21:15 */ SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for bjb -- ---------------------------- DROP TABLE IF EXISTS `bjb`; CREATE TABLE `bjb` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of bjb -- ---------------------------- INSERT INTO `bjb` VALUES ('1', '一班'); INSERT INTO `bjb` VALUES ('2', '2班'); INSERT INTO `bjb` VALUES ('3', '3班'); -- ---------------------------- -- Table structure for cjb -- ---------------------------- DROP TABLE IF EXISTS `cjb`; CREATE TABLE `cjb` ( `id` int(11) NOT NULL AUTO_INCREMENT, `id_sx` int(11) DEFAULT NULL, `yw` int(11) DEFAULT NULL, `sx` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of cjb -- ---------------------------- INSERT INTO `cjb` VALUES ('1', '1', '77', '67'); INSERT INTO `cjb` VALUES ('2', '2', '32', '27'); INSERT INTO `cjb` VALUES ('3', '3', '98', '78'); INSERT INTO `cjb` VALUES ('4', '4', '68', '63'); INSERT INTO `cjb` VALUES ('5', '5', '66', '77'); INSERT INTO `cjb` VALUES ('6', '6', '99', '88'); INSERT INTO `cjb` VALUES ('7', '7', '75', '45'); INSERT INTO `cjb` VALUES ('8', '8', '77', '88'); INSERT INTO `cjb` VALUES ('9', '9', '65', '81'); INSERT INTO `cjb` VALUES ('10', '10', '83', '89'); -- ---------------------------- -- Table structure for xsb -- ---------------------------- DROP TABLE IF EXISTS `xsb`; CREATE TABLE `xsb` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(20) DEFAULT NULL, `id_banji` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8; -- ---------------------------- -- Records of xsb -- ---------------------------- INSERT INTO `xsb` VALUES ('1', '岑', '1'); INSERT INTO `xsb` VALUES ('2', 'cen', '1'); INSERT INTO `xsb` VALUES ('3', 'y', '2'); INSERT INTO `xsb` VALUES ('4', 'u', '3'); INSERT INTO `xsb` VALUES ('5', 'yue', '2'); INSERT INTO `xsb` VALUES ('6', 'kk', '2'); INSERT INTO `xsb` VALUES ('7', 'tom', '1'); INSERT INTO `xsb` VALUES ('8', 'lili', '1'); INSERT INTO `xsb` VALUES ('9', 'kile', '3'); INSERT INTO `xsb` VALUES ('10', 'jack', '2'); INSERT INTO `xsb` VALUES ('11', 'hh', '2'); -- ---------------------------- -- Procedure structure for sp_add3 -- ---------------------------- DROP PROCEDURE IF EXISTS `sp_add3`; DELIMITER ;; CREATE DEFINER=`root`@`localhost` PROCEDURE `sp_add3`(a int, b int,out c int) begin set c=a+ b; end ;; DELIMITER ;
學生表【字段意思:學生id、姓名、班級id】
班級表【字段意思:班級id、班級名稱】
成績表【字段意思:成績id、學生id、語文成績、數學成績】
【注意:11號同學hh ,他沒有成績,他作弊被取消了考試資格,因此成績表沒有他的信息】
(1)查詢所有學生的信息
寫法一:
select x.id,x.name,b.name n from xsb x
left join bjb b on b.id = x.id_banji;
查詢結果
寫法二:
select x.id,x.name,b.name n2 from xsb x,bjb b
where b.id = x.id_banji;
查詢結果與上圖一樣
(2)查詢所有人的課程分數
寫法一:【查詢11號同學為null】
select x.name,b.name n ,c.yw ,c.sx from xsb x left join bjb b on b.id = x.id_banji left join cjb c on c.id_sx = x.id ;
查詢結果
寫法二:【查詢11號同學為0】
select x.name,b.name n , ifnull(c.yw,0) , ifnull(c.sx,0) from xsb x left join bjb b on b.id = x.id_banji left join cjb c on c.id_sx = x.id ;
查詢結果
寫法三:【查詢無11號同學】不使用left join會導致沒有成績的那個同學不顯示,因為直接連表查詢只會保留所有關聯條件成立的數據
select x.name,b.name n , ifnull(c.yw,0) , ifnull(c.sx,0) from xsb x,bjb b,cjb c WHERE b.id = x.id_banji and c.id_sx = x.id ;
查詢結果
(3)查詢語文分數比“yue”的高的學生,【 如果是查詢比“yue”的低, 不使用ifnull那么沒有成績的同學無法查看到】
select x.name,b.name n , ifnull(c.yw,0) from xsb x left join bjb b on b.id = x.id_banji left join cjb c on c.id_sx = x.id where ifnull(c.yw,0) > ( select c.yw from cjb c left join xsb x on c.id_sx = x.id where x.name= "yue" )
查詢結果
(4)查詢各科都合格【分數>=60分】的學生(姓名、語文分數、數學分數)
select x.name , c.yw ,c.sx from xsb x left join cjb c on c.id_sx =x.id WHERE c.yw>60 and c.sx >60
打印結果
(5)查詢總分數(語文+數學)>=150的學生信息(姓名、班級名稱、總分數)
select x.name,b.name n , ifnull(c.yw,0) as "語文",ifnull(c.sx,0) as "數學", #sum是運算函數 ,在里面可以做加減乘除 sum(ifnull(c.yw,0) + ifnull(c.sx,0)) as "總分" from xsb x left join bjb b on b.id = x.id_banji left join cjb c on c.id_sx = x.id where (ifnull(c.yw,0) +ifnull(c.sx,0)) >=150 #計算總分必須要分組,加上這個GROUP BY x.id,表示以一位學生為一組計算總分,否則會全部加在一起 GROUP BY x.id
查詢結果
(6)查詢沒有參加考試【沒有成績表】的學生(姓名、班級名稱)
寫法一:
select x.name,b.name n from xsb x left join bjb b on b.id = x.id_banji left join cjb c on c.id_sx = x.id where x.id not in (select id_sx from cjb);
查詢結果
寫法二:
select x.name,b.name n from xsb x ,bjb b ,cjb c WHERE x.id_banji = b.id and x.id not in (select id_sx from cjb) GROUP BY x.name,b.name ;
查詢結果與上圖一樣
(7)假設分數>=60分合格,分析學生的成績是否合格
select x.name,if(c.yw>=60,"合格","不合格") as "語文成績" , if(c.sx>=60,"合格","不合格") as "數學成績" from xsb x left join cjb c on c.id_sx = x.id
查詢結果
(8)查詢有掛科【分數<60分】現象的學生(姓名、語文分數、數學分數)
select x.name ,ifnull( c.yw ,0),ifnull(c.sx,0) from xsb x left join cjb c on c.id_sx =x.id WHERE ifnull( c.yw ,0) <60 or ifnull(c.sx,0)<60;
查詢結果
(9)查詢所有班級的平均分數(班級編號、班級名稱、語文平均分數、數學平均分數)
寫法一:
select b.name , AVG(c.yw) as "語文平均分數" ,AVG(c.sx) as "數學平均分數" from xsb x left join bjb b on b.id = x.id_banji left join cjb c on c.id_sx = x.id GROUP BY b.id ;
查詢結果
寫法二:【主從表換了沒影響】
select b.name , AVG(c.yw) as "語文平均分數" ,AVG(c.sx) as "數學平均分數" from bjb b left join xsb x on b.id = x.id_banji left join cjb c on c.id_sx = x.id GROUP BY b.id
查詢結果與上圖一樣
(10)查詢班級人數>=3的班級(班級編號、班級名稱、人數)
select b.id ,b.name , count(x.id) as "人數" from bjb b left join xsb x on b.id = x.id_banji #HAVING 子句可以讓我們篩選分組后的各組數據。 group by b.id having count(x.id) >=3
查詢結果