1. 程式人生 > >SQL語句彙總(終篇)—— 表聯接與聯接查詢

SQL語句彙總(終篇)—— 表聯接與聯接查詢

上一篇博文說到相關子查詢效率低下,那我們怎麼能將不同表的資訊一起查詢出來呢?這就需要用到表聯接。

和之前的UNION組合查詢不同,UNION是將不同的表組合起來,也就是縱向聯接,說白了就是豎著拼起來。

而表聯接是通過笛卡爾乘積將表進行橫向聯接,所謂的通過笛卡爾乘積簡單說就是兩表的行依次相聯再相加。要想更詳細的理解可以百度下,畢竟本文主要是彙總SQL語句。
現在有兩張表: t_student 和 t_class
建表語句:

CREATE TABLE `t_student` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `name` varchar(10) NOT NULL COMMENT '姓名',
  `age` int(3) unsigned NOT NULL COMMENT '年齡',
  `code` varchar(5) NOT NULL DEFAULT '' COMMENT '行業',
  `sex` varchar(5) NOT NULL DEFAULT '男' COMMENT '性別',
  `fk` int(11) NOT NULL DEFAULT '0' COMMENT '班級id',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
INSERT INTO `t_student` VALUES (1, '大毛', 18, '新聞', '男', 1);
INSERT INTO `t_student` VALUES (2, '王二', 20, '網路', '男', 2);
INSERT INTO `t_student` VALUES (3, '張三', 22, 'IT', '男', 3);
INSERT INTO `t_student` VALUES (4, '李四', 17, 'IT', '女', 4);
INSERT INTO `t_student` VALUES (5, '王五', 23, '財務', '男', 2);
INSERT INTO `t_student` VALUES (6, '王大雷', 21, '新聞', '男', 1);
INSERT INTO `t_student` VALUES (7, '阿迪王', 20, '網路', '男', 4);
INSERT INTO `t_student` VALUES (8, '姓王的', 24, '新聞', '男', 3);
INSERT INTO `t_student` VALUES (9, '大王', 25, 'IT', '男', 1);
INSERT INTO `t_student` VALUES (10, '大黃', 20, 'IT', '男', 4);

在這裡插入圖片描述

CREATE TABLE `t_class` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  `code` varchar(10) NOT NULL,
  `info` int(11) NOT NULL,
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `class_name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
INSERT INTO `t_class` VALUES (1, '一班', 't1', 1);
INSERT INTO `t_class` VALUES (2, '二班', 't2', 2);
INSERT INTO `t_class` VALUES (3, '三班', 't3', 3);
INSERT INTO `t_class` VALUES (4, '四班', 't4', 4);
INSERT INTO `t_class` VALUES (5, '五班', 't5', 5);

在這裡插入圖片描述
怎麼聯接這兩張表呢?標準寫法:

SELECT * FROM t_student JOIN t_class 

結果這裡只截一小部分圖,因為笛卡爾乘積後的行數等於兩張表的行數乘積,實在太多了。
在這裡插入圖片描述

這裡就可以理解表聯接的原理了,依次相連再相加。當然其中很多是無效行,為了去除無效的行我們就要用到外來鍵來進行約束。學生表中的fk與班級表中的infor相關聯:

select s.*,c.name cname from t_student s JOIN t_class c on s.fk = c.info

在這裡插入圖片描述

這裡通過外來鍵的匹配我們就得到了一張完美的聯接之後的表,它可以看做一張新表,想要任何資料均可以從此表中查詢,這就是表聯接的強大之處。

表聯接的分類:

內聯接:

內聯接是指兩個表中某一行相關的列值匹配時,這一行才會出現在表中。就像上例中s._fk與c._infor相同時才會出行該行,其他的行剔除。

語法為INNER JOIN 其中INNER可以省略。

內聯接的簡寫:

select s.*,c.name cname from t_student s ,t_class c on s.fk = c.info
  • 此寫法也是我們用的最多的。

外聯接:

分為左外聯接與右處聯接。

外聯接是指不管有沒有匹配,被定義了外聯接的表資料都要出現在結果中。比如左外聯接,那麼在JOIN左邊的表就被定義為外聯接,那麼此表中所有資料都會出現在查詢結果中。
注意班級表中的五班是沒有學生的,所以在內聯接之後理所當然的被剔除了。現在以外聯接做示例:

SELECT * FROM t_student s RIGHT JOIN t_class c ON s.fk=c.info; 

在這裡插入圖片描述
最下面多了一行五班的資訊
例如我們想查出還沒有學生錄入的班級資訊:

SELECT c.id,c.name FROM t_student s RIGHT JOIN t_class c ON s.fk=c.info where s.id is null; 

在這裡插入圖片描述

這就是外聯接的用法,通常用在我們想要的資料匹配不上時。

知識點羅列到這裡,做題時間到:

1.查詢王大雷所在的班級

select s.*,c.name cname from t_student s , t_class c where  s.fk = c.info and s.name = '王大雷'

在這裡插入圖片描述

2.查詢同王大雷同班級的學生

select s.name from t_student s where s.fk = (select fk from t_student where name = '王大雷') and s.name != '王大雷'

在這裡插入圖片描述

3.查詢每個班級的人數

SELECT d.cname,COUNT(d.name) FROM (SELECT ss.*,cc.name cname FROM t_class cc LEFT JOIN t_student ss ON ss.fk = cc.info) d GROUP BY d.cname;

在這裡插入圖片描述

4.查詢班級人數最多的班級

SELECT d.cname,COUNT(d.name) count FROM (SELECT ss.*,cc.name cname FROM t_class cc LEFT JOIN t_student ss ON ss.fk = cc.info) d GROUP BY d.cname HAVING count >=ALL(SELECT COUNT(d.name) count FROM (SELECT ss.*,cc.name cname FROM t_class cc LEFT JOIN t_student ss ON ss.fk = cc.info) d GROUP BY d.cname);

在這裡插入圖片描述

5.查詢每個班中年齡最低的人

select s.*,c.name from t_student s left join t_class c on c.info = s.fk where s.age <= (select min(age) from t_student )

在這裡插入圖片描述