MySQL(記錄相關操做-多表查詢)

1、介紹

本節主題mysql

  • 多表鏈接查詢
  • 複合條件鏈接查詢
  • 子查詢

準備表sql

#建表
create table department(
id int,
name varchar(20) 
);

create table employee(
id int primary key auto_increment,
name varchar(20),
sex enum('male','female') not null default 'male',
age int,
dep_id int
);

#插入數據
insert into department values
(200,'技術'),
(201,'人力資源'),
(202,'銷售'),
(203,'運營');

insert into employee(name,sex,age,dep_id) values
('egon','male',18,200),
('alex','female',48,201),
('wupeiqi','male',38,201),
('yuanhao','female',28,202),
('liwenzhou','male',18,200),
('jingliyang','female',18,204)
;


#查看錶結構和數據
mysql> desc department;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(20) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+

mysql> desc employee;
+--------+-----------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+-----------------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(20) | YES | | NULL | |
| sex | enum('male','female') | NO | | male | |
| age | int(11) | YES | | NULL | |
| dep_id | int(11) | YES | | NULL | |
+--------+-----------------------+------+-----+---------+----------------+

mysql> select * from department;
+------+--------------+
| id | name |
+------+--------------+
| 200 | 技術 |
| 201 | 人力資源 |
| 202 | 銷售 |
| 203 | 運營 |
+------+--------------+

mysql> select * from employee;
+----+------------+--------+------+--------+
| id | name | sex | age | dep_id |
+----+------------+--------+------+--------+
| 1 | egon | male | 18 | 200 |
| 2 | alex | female | 48 | 201 |
| 3 | wupeiqi | male | 38 | 201 |
| 4 | yuanhao | female | 28 | 202 |
| 5 | liwenzhou | male | 18 | 200 |
| 6 | jingliyang | female | 18 | 204 |
+----+------------+--------+------+--------+
表department與employee

2、多表鏈接查詢

#重點:外連接語法

SELECT 字段列表
    FROM 表1 INNER|LEFT|RIGHT JOIN 表2
    ON 表1.字段 = 表2.字段;

 一、交叉鏈接:不適用任何匹配條件。生成笛卡爾積

mysql> select * from employee,department;
+----+------------+--------+------+--------+------+--------------+
| id | name       | sex    | age  | dep_id | id   | name         |
+----+------------+--------+------+--------+------+--------------+
|  1 | egon       | male   |   18 |    200 |  200 | 技術         |
|  1 | egon       | male   |   18 |    200 |  201 | 人力資源     |
|  1 | egon       | male   |   18 |    200 |  202 | 銷售         |
|  1 | egon       | male   |   18 |    200 |  203 | 運營         |
|  2 | alex       | female |   48 |    201 |  200 | 技術         |
|  2 | alex       | female |   48 |    201 |  201 | 人力資源     |
|  2 | alex       | female |   48 |    201 |  202 | 銷售         |
|  2 | alex       | female |   48 |    201 |  203 | 運營         |
|  3 | wupeiqi    | male   |   38 |    201 |  200 | 技術         |
|  3 | wupeiqi    | male   |   38 |    201 |  201 | 人力資源     |
|  3 | wupeiqi    | male   |   38 |    201 |  202 | 銷售         |
|  3 | wupeiqi    | male   |   38 |    201 |  203 | 運營         |
|  4 | yuanhao    | female |   28 |    202 |  200 | 技術         |
|  4 | yuanhao    | female |   28 |    202 |  201 | 人力資源     |
|  4 | yuanhao    | female |   28 |    202 |  202 | 銷售         |
|  4 | yuanhao    | female |   28 |    202 |  203 | 運營         |
|  5 | liwenzhou  | male   |   18 |    200 |  200 | 技術         |
|  5 | liwenzhou  | male   |   18 |    200 |  201 | 人力資源     |
|  5 | liwenzhou  | male   |   18 |    200 |  202 | 銷售         |
|  5 | liwenzhou  | male   |   18 |    200 |  203 | 運營         |
|  6 | jingliyang | female |   18 |    204 |  200 | 技術         |
|  6 | jingliyang | female |   18 |    204 |  201 | 人力資源     |
|  6 | jingliyang | female |   18 |    204 |  202 | 銷售         |
|  6 | jingliyang | female |   18 |    204 |  203 | 運營         |
+----+------------+--------+------+--------+------+--------------+

二、內鏈接:只鏈接匹配的行

#找兩張表共有的部分,至關於利用條件從笛卡爾積結果中篩選出了正確的結果
#department沒有204這個部門,於是employee表中關於204這條員工信息沒有匹配出來
mysql> select employee.id,employee.name,employee.age,employee.sex,department.name from employee inner join department on employee.dep_id=department.id; 
+----+-----------+------+--------+--------------+
| id | name      | age  | sex    | name         |
+----+-----------+------+--------+--------------+
|  1 | egon      |   18 | male   | 技術         |
|  2 | alex      |   48 | female | 人力資源     |
|  3 | wupeiqi   |   38 | male   | 人力資源     |
|  4 | yuanhao   |   28 | female | 銷售         |
|  5 | liwenzhou |   18 | male   | 技術         |
+----+-----------+------+--------+--------------+

#上述sql等同於
mysql> select employee.id,employee.name,employee.age,employee.sex,department.name from employee,department where employee.dep_id=department.id;

三、外連接之左鏈接:優先顯示左表所有記錄

#以左表爲準,即找出全部員工信息,固然包括沒有部門的員工
#本質就是:在內鏈接的基礎上增長左邊有右邊沒有的結果
mysql> select employee.id,employee.name,department.name as depart_name from employee left join department on employee.dep_id=department.id;
+----+------------+--------------+
| id | name       | depart_name  |
+----+------------+--------------+
|  1 | egon       | 技術         |
|  5 | liwenzhou  | 技術         |
|  2 | alex       | 人力資源     |
|  3 | wupeiqi    | 人力資源     |
|  4 | yuanhao    | 銷售         |
|  6 | jingliyang | NULL         |
+----+------------+--------------+

四、外連接之右鏈接:優先顯示右表所有記錄

#以右表爲準,即找出全部部門信息,包括沒有員工的部門
#本質就是:在內鏈接的基礎上增長右邊有左邊沒有的結果
mysql> select employee.id,employee.name,department.name as depart_name from employee right join department on employee.dep_id=department.id;
+------+-----------+--------------+
| id   | name      | depart_name  |
+------+-----------+--------------+
|    1 | egon      | 技術         |
|    2 | alex      | 人力資源     |
|    3 | wupeiqi   | 人力資源     |
|    4 | yuanhao   | 銷售         |
|    5 | liwenzhou | 技術         |
| NULL | NULL      | 運營         |
+------+-----------+--------------+

五、全外鏈接:顯示左右兩個表所有記錄

全外鏈接:在內鏈接的基礎上增長左邊有右邊沒有的和右邊有左邊沒有的結果
#注意:mysql不支持全外鏈接 full JOIN
#強調:mysql可使用此種方式間接實現全外鏈接
select * from employee left join department on employee.dep_id = department.id
union
select * from employee right join department on employee.dep_id = department.id
;
#查看結果
+------+------------+--------+------+--------+------+--------------+
| id   | name       | sex    | age  | dep_id | id   | name         |
+------+------------+--------+------+--------+------+--------------+
|    1 | egon       | male   |   18 |    200 |  200 | 技術         |
|    5 | liwenzhou  | male   |   18 |    200 |  200 | 技術         |
|    2 | alex       | female |   48 |    201 |  201 | 人力資源     |
|    3 | wupeiqi    | male   |   38 |    201 |  201 | 人力資源     |
|    4 | yuanhao    | female |   28 |    202 |  202 | 銷售         |
|    6 | jingliyang | female |   18 |    204 | NULL | NULL         |
| NULL | NULL       | NULL   | NULL |   NULL |  203 | 運營         |
+------+------------+--------+------+--------+------+--------------+

#注意 union與union all的區別:union會去掉相同的紀錄

3、符合條件鏈接查詢

#示例1:之內鏈接的方式查詢employee和department表,而且employee表中的age字段值必須大於25,即找出年齡大於25歲的員工以及員工所在的部門
select employee.name,department.name from employee inner join department
    on employee.dep_id = department.id
    where age > 25;

#示例2:之內鏈接的方式查詢employee和department表,而且以age字段的升序方式顯示
select employee.id,employee.name,employee.age,department.name from employee,department
    where employee.dep_id = department.id
    and age > 25
    order by age asc;

4、子查詢

#1:子查詢是將一個查詢語句嵌套在另外一個查詢語句中。
#2:內層查詢語句的查詢結果,能夠爲外層查詢語句提供查詢條件。
#3:子查詢中能夠包含:INNOT INANYALLEXISTSNOT EXISTS等關鍵字
#4:還能夠包含比較運算符:=!=><

一、帶IN關鍵字的子查詢

#查詢平均年齡在25歲以上的部門名
select id,name from department
    where id in 
        (select dep_id from employee group by dep_id having avg(age) > 25);

#查看技術部員工姓名
select name from employee
    where dep_id in 
        (select id from department where name='技術');

#查看不足1人的部門名(子查詢獲得的是有人的部門id)
select name from department where id not in (select distinct dep_id from employee);

二、帶比較運算符的子查詢

#比較運算符:=!=>>=<<=<>
#查詢大於全部人平均年齡的員工名與年齡
mysql> select name,age from emp where age > (select avg(age) from emp);
+---------+------+
| name | age |
+---------+------+
| alex | 48 |
| wupeiqi | 38 |
+---------+------+
2 rows in set (0.00 sec)


#查詢大於部門內平均年齡的員工名、年齡
select t1.name,t1.age from emp t1
inner join 
(select dep_id,avg(age) avg_age from emp group by dep_id) t2
on t1.dep_id = t2.dep_id
where t1.age > t2.avg_age; 

三、帶EXISTS關鍵字的子查詢

EXISTS關字鍵字表示存在。在使用EXISTS關鍵字時,內層查詢語句不返回查詢的記錄。
而是返回一個真假值。True或False
當返回True時,外層查詢語句將進行查詢;當返回值爲False時,外層查詢語句不進行查詢
#department表中存在dept_id=203,Ture
mysql> select * from employee
    ->     where exists
    ->         (select id from department where id=200);
+----+------------+--------+------+--------+
| id | name       | sex    | age  | dep_id |
+----+------------+--------+------+--------+
|  1 | egon       | male   |   18 |    200 |
|  2 | alex       | female |   48 |    201 |
|  3 | wupeiqi    | male   |   38 |    201 |
|  4 | yuanhao    | female |   28 |    202 |
|  5 | liwenzhou  | male   |   18 |    200 |
|  6 | jingliyang | female |   18 |    204 |
+----+------------+--------+------+--------+

#department表中存在dept_id=205,False
mysql> select * from employee
    ->     where exists
    ->         (select id from department where id=204);
Empty set (0.00 sec)

四、練習:查詢每一個部門最新入職的那位員工

company.employee
    員工id      id                  int             
    姓名        emp_name            varchar
    性別        sex                 enum
    年齡        age                 int
    入職日期     hire_date           date
    崗位        post                varchar
    職位描述     post_comment        varchar
    薪水        salary              double
    辦公室       office              int
    部門編號     depart_id           int



#建立表
create table employee(
id int not null unique auto_increment,
name varchar(20) not null,
sex enum('male','female') not null default 'male', #大部分是男的
age int(3) unsigned not null default 28,
hire_date date not null,
post varchar(50),
post_comment varchar(100),
salary double(15,2),
office int, #一個部門一個屋子
depart_id int
);


#查看錶結構
mysql> desc employee;
+--------------+-----------------------+------+-----+---------+----------------+
| Field        | Type                  | Null | Key | Default | Extra          |
+--------------+-----------------------+------+-----+---------+----------------+
| id           | int(11)               | NO   | PRI | NULL    | auto_increment |
| name         | varchar(20)           | NO   |     | NULL    |                |
| sex          | enum('male','female') | NO   |     | male    |                |
| age          | int(3) unsigned       | NO   |     | 28      |                |
| hire_date    | date                  | NO   |     | NULL    |                |
| post         | varchar(50)           | YES  |     | NULL    |                |
| post_comment | varchar(100)          | YES  |     | NULL    |                |
| salary       | double(15,2)          | YES  |     | NULL    |                |
| office       | int(11)               | YES  |     | NULL    |                |
| depart_id    | int(11)               | YES  |     | NULL    |                |
+--------------+-----------------------+------+-----+---------+----------------+

#插入記錄
#三個部門:教學,銷售,運營
insert into employee(name,sex,age,hire_date,post,salary,office,depart_id) values
('egon','male',18,'20170301','老男孩駐沙河辦事處外交大使',7300.33,401,1), #如下是教學部
('alex','male',78,'20150302','teacher',1000000.31,401,1),
('wupeiqi','male',81,'20130305','teacher',8300,401,1),
('yuanhao','male',73,'20140701','teacher',3500,401,1),
('liwenzhou','male',28,'20121101','teacher',2100,401,1),
('jingliyang','female',18,'20110211','teacher',9000,401,1),
('jinxin','male',18,'19000301','teacher',30000,401,1),
('成龍','male',48,'20101111','teacher',10000,401,1),

('歪歪','female',48,'20150311','sale',3000.13,402,2),#如下是銷售部門
('丫丫','female',38,'20101101','sale',2000.35,402,2),
('丁丁','female',18,'20110312','sale',1000.37,402,2),
('星星','female',18,'20160513','sale',3000.29,402,2),
('格格','female',28,'20170127','sale',4000.33,402,2),

('張野','male',28,'20160311','operation',10000.13,403,3), #如下是運營部門
('程咬金','male',18,'19970312','operation',20000,403,3),
('程咬銀','female',18,'20130311','operation',19000,403,3),
('程咬銅','male',18,'20150411','operation',18000,403,3),
('程咬鐵','female',18,'20140512','operation',17000,403,3)
;

#ps:若是在windows系統中,插入中文字符,select的結果爲空白,能夠將全部字符編碼統一設置成gbk
準備表和記錄
SELECT
    *
FROM
    employee AS t1
INNER JOIN (
    SELECT
        post,
        max(hire_date) max_date
    FROM
        employee
    GROUP BY
        post
) AS t2 ON t1.post = t2.post
WHERE
    t1.hire_date = t2.max_date;
答案一(鏈表)
mysql> select (select t2.name from emp as t2 where t2.post=t1.post order by hire_date desc limit 1) from emp as t1 group by post;
+---------------------------------------------------------------------------------------+
| (select t2.name from emp as t2 where t2.post=t1.post order by hire_date desc limit 1) |
+---------------------------------------------------------------------------------------+
| 張野                                                                                  |
| 格格                                                                                  |
| alex                                                                                  |
| egon                                                                                  |
+---------------------------------------------------------------------------------------+
rows in set (0.00 sec)

mysql> select (select t2.id from emp as t2 where t2.post=t1.post order by hire_date desc limit 1) from emp as t1 group by post;
+-------------------------------------------------------------------------------------+
| (select t2.id from emp as t2 where t2.post=t1.post order by hire_date desc limit 1) |
+-------------------------------------------------------------------------------------+
|                                                                                  14 |
|                                                                                  13 |
|                                                                                   2 |
|                                                                                   1 |
+-------------------------------------------------------------------------------------+
rows in set (0.00 sec)

#正確答案
mysql> select t3.name,t3.post,t3.hire_date from emp as t3 where id in (select (select id from emp as t2 where t2.post=t1.post order by hire_date desc limit 1) from emp as t1 group by post);
+--------+-----------------------------------------+------------+
| name   | post                                    | hire_date  |
+--------+-----------------------------------------+------------+
| egon   | 老男孩駐沙河辦事處外交大使              | 2017-03-01 |
| alex   | teacher                                 | 2015-03-02 |
| 格格   | sale                                    | 2017-01-27 |
| 張野   | operation                               | 2016-03-11 |
+--------+-----------------------------------------+------------+
rows in set (0.00 sec)
答案二(子查詢)

答案一爲正確答案,答案二中的limit 1有問題(每一個部門可能有>1個爲同一時間入職的新員工),我只是想用該例子來講明能夠在select後使用子查詢windows

能夠基於上述方法解決:好比某網站在全國各個市都有站點,每一個站點一條數據,想取每一個省下最新的那一條市的網站質量信息。ide

5、綜合練習

init.sql文件內容post

/*
 數據導入:
 Navicat Premium Data Transfer

 Source Server         : localhost
 Source Server Type    : MySQL
 Source Server Version : 50624
 Source Host           : localhost
 Source Database       : sqlexam

 Target Server Type    : MySQL
 Target Server Version : 50624
 File Encoding         : utf-8

 Date: 10/21/2016 06:46:46 AM
*/

SET NAMES utf8;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
--  Table structure for `class`
-- ----------------------------
DROP TABLE IF EXISTS `class`;
CREATE TABLE `class` (
  `cid` int(11) NOT NULL AUTO_INCREMENT,
  `caption` varchar(32) NOT NULL,
  PRIMARY KEY (`cid`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `class`
-- ----------------------------
BEGIN;
INSERT INTO `class` VALUES ('1', '三年二班'), ('2', '三年三班'), ('3', '一年二班'), ('4', '二年九班');
COMMIT;

-- ----------------------------
--  Table structure for `course`
-- ----------------------------
DROP TABLE IF EXISTS `course`;
CREATE TABLE `course` (
  `cid` int(11) NOT NULL AUTO_INCREMENT,
  `cname` varchar(32) NOT NULL,
  `teacher_id` int(11) NOT NULL,
  PRIMARY KEY (`cid`),
  KEY `fk_course_teacher` (`teacher_id`),
  CONSTRAINT `fk_course_teacher` FOREIGN KEY (`teacher_id`) REFERENCES `teacher` (`tid`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `course`
-- ----------------------------
BEGIN;
INSERT INTO `course` VALUES ('1', '生物', '1'), ('2', '物理', '2'), ('3', '體育', '3'), ('4', '美術', '2');
COMMIT;

-- ----------------------------
--  Table structure for `score`
-- ----------------------------
DROP TABLE IF EXISTS `score`;
CREATE TABLE `score` (
  `sid` int(11) NOT NULL AUTO_INCREMENT,
  `student_id` int(11) NOT NULL,
  `course_id` int(11) NOT NULL,
  `num` int(11) NOT NULL,
  PRIMARY KEY (`sid`),
  KEY `fk_score_student` (`student_id`),
  KEY `fk_score_course` (`course_id`),
  CONSTRAINT `fk_score_course` FOREIGN KEY (`course_id`) REFERENCES `course` (`cid`),
  CONSTRAINT `fk_score_student` FOREIGN KEY (`student_id`) REFERENCES `student` (`sid`)
) ENGINE=InnoDB AUTO_INCREMENT=53 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `score`
-- ----------------------------
BEGIN;
INSERT INTO `score` VALUES ('1', '1', '1', '10'), ('2', '1', '2', '9'), ('5', '1', '4', '66'), ('6', '2', '1', '8'), ('8', '2', '3', '68'), ('9', '2', '4', '99'), ('10', '3', '1', '77'), ('11', '3', '2', '66'), ('12', '3', '3', '87'), ('13', '3', '4', '99'), ('14', '4', '1', '79'), ('15', '4', '2', '11'), ('16', '4', '3', '67'), ('17', '4', '4', '100'), ('18', '5', '1', '79'), ('19', '5', '2', '11'), ('20', '5', '3', '67'), ('21', '5', '4', '100'), ('22', '6', '1', '9'), ('23', '6', '2', '100'), ('24', '6', '3', '67'), ('25', '6', '4', '100'), ('26', '7', '1', '9'), ('27', '7', '2', '100'), ('28', '7', '3', '67'), ('29', '7', '4', '88'), ('30', '8', '1', '9'), ('31', '8', '2', '100'), ('32', '8', '3', '67'), ('33', '8', '4', '88'), ('34', '9', '1', '91'), ('35', '9', '2', '88'), ('36', '9', '3', '67'), ('37', '9', '4', '22'), ('38', '10', '1', '90'), ('39', '10', '2', '77'), ('40', '10', '3', '43'), ('41', '10', '4', '87'), ('42', '11', '1', '90'), ('43', '11', '2', '77'), ('44', '11', '3', '43'), ('45', '11', '4', '87'), ('46', '12', '1', '90'), ('47', '12', '2', '77'), ('48', '12', '3', '43'), ('49', '12', '4', '87'), ('52', '13', '3', '87');
COMMIT;

-- ----------------------------
--  Table structure for `student`
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student` (
  `sid` int(11) NOT NULL AUTO_INCREMENT,
  `gender` char(1) NOT NULL,
  `class_id` int(11) NOT NULL,
  `sname` varchar(32) NOT NULL,
  PRIMARY KEY (`sid`),
  KEY `fk_class` (`class_id`),
  CONSTRAINT `fk_class` FOREIGN KEY (`class_id`) REFERENCES `class` (`cid`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `student`
-- ----------------------------
BEGIN;
INSERT INTO `student` VALUES ('1', '', '1', '理解'), ('2', '', '1', '鋼蛋'), ('3', '', '1', '張三'), ('4', '', '1', '張一'), ('5', '', '1', '張二'), ('6', '', '1', '張四'), ('7', '', '2', '鐵錘'), ('8', '', '2', '李三'), ('9', '', '2', '李一'), ('10', '', '2', '李二'), ('11', '', '2', '李四'), ('12', '', '3', '如花'), ('13', '', '3', '劉三'), ('14', '', '3', '劉一'), ('15', '', '3', '劉二'), ('16', '', '3', '劉四');
COMMIT;

-- ----------------------------
--  Table structure for `teacher`
-- ----------------------------
DROP TABLE IF EXISTS `teacher`;
CREATE TABLE `teacher` (
  `tid` int(11) NOT NULL AUTO_INCREMENT,
  `tname` varchar(32) NOT NULL,
  PRIMARY KEY (`tid`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8;

-- ----------------------------
--  Records of `teacher`
-- ----------------------------
BEGIN;
INSERT INTO `teacher` VALUES ('1', '張磊老師'), ('2', '李平老師'), ('3', '劉海燕老師'), ('4', '朱雲海老師'), ('5', '李傑老師');
COMMIT;

SET FOREIGN_KEY_CHECKS = 1;
init.sql文件內容

從init.sql文件中導入數據網站

#準備表、記錄 mysql> create database db1;
mysql> use db1;
mysql> source /root/init.sql編碼

表結構爲spa

一SELECT語句關鍵字的定義順序SELECTDISTINCT<select_list>FROM<left_table><join_type>JOIN<right_table>ON<join_condition>WHERE<where_condition>GROUPBY<group_by_list>HAVING<having_condition>ORDERBY<order_by_condition>LIMIT<limit_number>二SELECT語句關鍵字的執行順序(7)SELECT(8)DISTINCT<select_list>(1)FROM<left_table>(3)<join_type>JOIN<right_table>(2)ON<join_condition>(4)WHERE<where_condition>(5)GROUPBY<group_by_list>(6)HAVING<having_condition>(9)ORDERBY<order_by_condition>(10)LIMIT<limit_number>
注意sql語句的執行順序
1、查詢全部的課程的名稱以及對應的任課老師姓名

2、查詢學生表中男女生各有多少人

3、查詢物理成績等於100的學生的姓名

4、查詢平均成績大於八十分的同窗的姓名和平均成績

5、查詢全部學生的學號,姓名,選課數,總成績

6、 查詢姓李老師的個數

7、 查詢沒有報李平老師課的學生姓名

8、 查詢物理課程比生物課程高的學生的學號

9、 查詢沒有同時選修物理課程和體育課程的學生姓名

10、查詢掛科超過兩門(包括兩門)的學生姓名和班級
、查詢選修了全部課程的學生姓名

12、查詢李平老師教的課程的全部成績記錄
 
13、查詢所有學生都選修了的課程號和課程名

14、查詢每門課程被選修的次數

15、查詢之選修了一門課程的學生姓名和學號

16、查詢全部學生考出的成績並按從高到低排序(成績去重)

17、查詢平均成績大於85的學生姓名和平均成績

18、查詢生物成績不及格的學生姓名和對應生物分數

19、查詢在全部選修了李平老師課程的學生中,這些課程(李平老師的課程,不是全部課程)平均成績最高的學生姓名

20、查詢每門課程成績最好的前兩名學生姓名

21、查詢不一樣課程但成績相同的學號,課程號,成績

22、查詢沒學過「葉平」老師課程的學生姓名以及選修的課程名稱;

23、查詢全部選修了學號爲1的同窗選修過的一門或者多門課程的同窗學號和姓名;

24、任課最多的老師中學生單科成績最高的學生姓名
題目
#1、查詢全部的課程的名稱以及對應的任課老師姓名
SELECT
    course.cname,
    teacher.tname
FROM
    course
INNER JOIN teacher ON course.teacher_id = teacher.tid;




#2、查詢學生表中男女生各有多少人
SELECT
    gender 性別,
    count(1) 人數
FROM
    student
GROUP BY
    gender;




#3、查詢物理成績等於100的學生的姓名
SELECT
    student.sname
FROM
    student
WHERE
    sid IN (
        SELECT
            student_id
        FROM
            score
        INNER JOIN course ON score.course_id = course.cid
        WHERE
            course.cname = '物理'
        AND score.num = 100
    );




#4、查詢平均成績大於八十分的同窗的姓名和平均成績
SELECT
    student.sname,
    t1.avg_num
FROM
    student
INNER JOIN (
    SELECT
        student_id,
        avg(num) AS avg_num
    FROM
        score
    GROUP BY
        student_id
    HAVING
        avg(num) > 80
) AS t1 ON student.sid = t1.student_id;




#5、查詢全部學生的學號,姓名,選課數,總成績(注意:對於那些沒有選修任何課程的學生也算在內)
SELECT
    student.sid,
    student.sname,
    t1.course_num,
    t1.total_num
FROM
    student
LEFT JOIN (
    SELECT
        student_id,
        COUNT(course_id) course_num,
        sum(num) total_num
    FROM
        score
    GROUP BY
        student_id
) AS t1 ON student.sid = t1.student_id;




#6、 查詢姓李老師的個數
SELECT
    count(tid)
FROM
    teacher
WHERE
    tname LIKE '李%';




#7、 查詢沒有報李平老師課的學生姓名(找出報名李平老師課程的學生,而後取反就能夠)
SELECT
    student.sname
FROM
    student
WHERE
    sid NOT IN (
        SELECT DISTINCT
            student_id
        FROM
            score
        WHERE
            course_id IN (
                SELECT
                    course.cid
                FROM
                    course
                INNER JOIN teacher ON course.teacher_id = teacher.tid
                WHERE
                    teacher.tname = '李平老師'
            )
    );




#8、 查詢物理課程比生物課程高的學生的學號(分別獲得物理成績表與生物成績表,而後連表便可)
SELECT
    t1.student_id
FROM
    (
        SELECT
            student_id,
            num
        FROM
            score
        WHERE
            course_id = (
                SELECT
                    cid
                FROM
                    course
                WHERE
                    cname = '物理'
            )
    ) AS t1
INNER JOIN (
    SELECT
        student_id,
        num
    FROM
        score
    WHERE
        course_id = (
            SELECT
                cid
            FROM
                course
            WHERE
                cname = '生物'
        )
) AS t2 ON t1.student_id = t2.student_id
WHERE
    t1.num > t2.num;




#9、 查詢沒有同時選修物理課程和體育課程的學生姓名(沒有同時選修指的是選修了一門的,思路是獲得物理+體育課程的學生信息表,而後基於學生分組,統計count(課程)=1)
SELECT
    student.sname
FROM
    student
WHERE
    sid IN (
        SELECT
            student_id
        FROM
            score
        WHERE
            course_id IN (
                SELECT
                    cid
                FROM
                    course
                WHERE
                    cname = '物理'
                OR cname = '體育'
            )
        GROUP BY
            student_id
        HAVING
            COUNT(course_id) = 1
    );




#10、查詢掛科超過兩門(包括兩門)的學生姓名和班級(求出<60的表,而後對學生進行分組,統計課程數目>=2)
SELECT
    student.sname,
    class.caption
FROM
    student
INNER JOIN (
    SELECT
        student_id
    FROM
        score
    WHERE
        num < 60
    GROUP BY
        student_id
    HAVING
        count(course_id) >= 2
) AS t1
INNER JOIN class ON student.sid = t1.student_id
AND student.class_id = class.cid;




#11、查詢選修了全部課程的學生姓名(先從course表統計課程的總數,而後基於score表按照student_id分組,統計課程數據等於課程總數便可)
SELECT
    student.sname
FROM
    student
WHERE
    sid IN (
        SELECT
            student_id
        FROM
            score
        GROUP BY
            student_id
        HAVING
            COUNT(course_id) = (SELECT count(cid) FROM course)
    );




#12、查詢李平老師教的課程的全部成績記錄
SELECT
    *
FROM
    score
WHERE
    course_id IN (
        SELECT
            cid
        FROM
            course
        INNER JOIN teacher ON course.teacher_id = teacher.tid
        WHERE
            teacher.tname = '李平老師'
    );




#13、查詢所有學生都選修了的課程號和課程名(取全部學生數,而後基於score表的課程分組,找出count(student_id)等於學生數便可)
SELECT
    cid,
    cname
FROM
    course
WHERE
    cid IN (
        SELECT
            course_id
        FROM
            score
        GROUP BY
            course_id
        HAVING
            COUNT(student_id) = (
                SELECT
                    COUNT(sid)
                FROM
                    student
            )
    );




#14、查詢每門課程被選修的次數
SELECT
    course_id,
    COUNT(student_id)
FROM
    score
GROUP BY
    course_id;




#15、查詢之選修了一門課程的學生姓名和學號
SELECT
    sid,
    sname
FROM
    student
WHERE
    sid IN (
        SELECT
            student_id
        FROM
            score
        GROUP BY
            student_id
        HAVING
            COUNT(course_id) = 1
    );




#16、查詢全部學生考出的成績並按從高到低排序(成績去重)
SELECT DISTINCT
    num
FROM
    score
ORDER BY
    num DESC;




#17、查詢平均成績大於85的學生姓名和平均成績
SELECT
    sname,
    t1.avg_num
FROM
    student
INNER JOIN (
    SELECT
        student_id,
        avg(num) avg_num
    FROM
        score
    GROUP BY
        student_id
    HAVING
        AVG(num) > 85
) t1 ON student.sid = t1.student_id;




#18、查詢生物成績不及格的學生姓名和對應生物分數
SELECT
    sname 姓名,
    num 生物成績
FROM
    score
LEFT JOIN course ON score.course_id = course.cid
LEFT JOIN student ON score.student_id = student.sid
WHERE
    course.cname = '生物'
AND score.num < 60;




#19、查詢在全部選修了李平老師課程的學生中,這些課程(李平老師的課程,不是全部課程)平均成績最高的學生姓名
SELECT
    sname
FROM
    student
WHERE
    sid = (
        SELECT
            student_id
        FROM
            score
        WHERE
            course_id IN (
                SELECT
                    course.cid
                FROM
                    course
                INNER JOIN teacher ON course.teacher_id = teacher.tid
                WHERE
                    teacher.tname = '李平老師'
            )
        GROUP BY
            student_id
        ORDER BY
            AVG(num) DESC
        LIMIT 1
    );




#20、查詢每門課程成績最好的前兩名學生姓名
#查看每門課程按照分數排序的信息,爲下列查找正確與否提供依據
SELECT
    *
FROM
    score
ORDER BY
    course_id,
    num DESC;




#表1:求出每門課程的課程course_id,與最高分數first_num
SELECT
    course_id,
    max(num) first_num
FROM
    score
GROUP BY
    course_id;




#表2:去掉最高分,再按照課程分組,取得的最高分,就是第二高的分數second_num
SELECT
    score.course_id,
    max(num) second_num
FROM
    score
INNER JOIN (
    SELECT
        course_id,
        max(num) first_num
    FROM
        score
    GROUP BY
        course_id
) AS t ON score.course_id = t.course_id
WHERE
    score.num < t.first_num
GROUP BY
    course_id;




#將表1和表2聯合到一塊兒,獲得一張表t3,包含課程course_id與該們課程的first_num與second_num
SELECT
    t1.course_id,
    t1.first_num,
    t2.second_num
FROM
    (
        SELECT
            course_id,
            max(num) first_num
        FROM
            score
        GROUP BY
            course_id
    ) AS t1
INNER JOIN (
    SELECT
        score.course_id,
        max(num) second_num
    FROM
        score
    INNER JOIN (
        SELECT
            course_id,
            max(num) first_num
        FROM
            score
        GROUP BY
            course_id
    ) AS t ON score.course_id = t.course_id
    WHERE
        score.num < t.first_num
    GROUP BY
        course_id
) AS t2 ON t1.course_id = t2.course_id;




#查詢前兩名的學生(有可能出現並列第一或者並列第二的狀況)
SELECT
    score.student_id,
    t3.course_id,
    t3.first_num,
    t3.second_num
FROM
    score
INNER JOIN (
    SELECT
        t1.course_id,
        t1.first_num,
        t2.second_num
    FROM
        (
            SELECT
                course_id,
                max(num) first_num
            FROM
                score
            GROUP BY
                course_id
        ) AS t1
    INNER JOIN (
        SELECT
            score.course_id,
            max(num) second_num
        FROM
            score
        INNER JOIN (
            SELECT
                course_id,
                max(num) first_num
            FROM
                score
            GROUP BY
                course_id
        ) AS t ON score.course_id = t.course_id
        WHERE
            score.num < t.first_num
        GROUP BY
            course_id
    ) AS t2 ON t1.course_id = t2.course_id
) AS t3 ON score.course_id = t3.course_id
WHERE
    score.num >= t3.second_num
AND score.num <= t3.first_num;




#排序後能夠看的明顯點
SELECT
    score.student_id,
    t3.course_id,
    t3.first_num,
    t3.second_num
FROM
    score
INNER JOIN (
    SELECT
        t1.course_id,
        t1.first_num,
        t2.second_num
    FROM
        (
            SELECT
                course_id,
                max(num) first_num
            FROM
                score
            GROUP BY
                course_id
        ) AS t1
    INNER JOIN (
        SELECT
            score.course_id,
            max(num) second_num
        FROM
            score
        INNER JOIN (
            SELECT
                course_id,
                max(num) first_num
            FROM
                score
            GROUP BY
                course_id
        ) AS t ON score.course_id = t.course_id
        WHERE
            score.num < t.first_num
        GROUP BY
            course_id
    ) AS t2 ON t1.course_id = t2.course_id
) AS t3 ON score.course_id = t3.course_id
WHERE
    score.num >= t3.second_num
AND score.num <= t3.first_num
ORDER BY
    course_id;




#能夠用如下命令驗證上述查詢的正確性
SELECT
    *
FROM
    score
ORDER BY
    course_id,
    num DESC;




-- 2一、查詢不一樣課程但成績相同的學號,課程號,成績
-- 2二、查詢沒學過「葉平」老師課程的學生姓名以及選修的課程名稱;
-- 2三、查詢全部選修了學號爲1的同窗選修過的一門或者多門課程的同窗學號和姓名;
-- 2四、任課最多的老師中學生單科成績最高的學生姓名
答案
相關文章
相關標籤/搜索