mysql联表查询多记录显示_数据库:MySQL(多表的表记录的查询)(三)
一、外鍵約束
1、創建外鍵
---每一個班主任會對應多個學生 , 而每個學生只能對應一個班主任----主表
CREATE TABLE ClassCharger(
id TINYINT PRIMARY KEY auto_increment,
name VARCHAR (20),
age INT ,
is_marriged boolean-- show create table ClassCharger: tinyint(1)
);
INSERT INTO ClassCharger (name,age,is_marriged) VALUES ("冰冰",12,0),
("丹丹",14,0),
("歪歪",22,0),
("姍姍",20,0),
("小雨",21,0);----子表
CREATE TABLE Student(
id INT PRIMARY KEY auto_increment,
name VARCHAR (20),
charger_id TINYINT,--切記:作為外鍵一定要和關聯主鍵的數據類型保持一致--[ADD CONSTRAINT charger_fk_stu]FOREIGN KEY (charger_id) REFERENCES ClassCharger(id)
) ENGINE=INNODB;
INSERT INTO Student(name,charger_id) VALUES ("alvin1",2),
("alvin2",4),
("alvin3",1),
("alvin4",3),
("alvin5",1),
("alvin6",3),
("alvin7",2);
DELETE FROM ClassCharger WHERE name="冰冰";
INSERT student (name,charger_id) VALUES ("yuan",1);-- 刪除居然成功,可是 alvin3顯示還是有班主任id=1的冰冰的;-----------增加外鍵和刪除外鍵---------ALTER TABLE student ADD CONSTRAINT abc
FOREIGN KEY(charger_id)
REFERENCES classcharger(id);
ALTER TABLE student DROP FOREIGN KEY abc;
2、 INNODB支持的ON語句
--外鍵約束對子表的含義: 如果在父表中找不到候選鍵,則不允許在子表上進行insert/update--外鍵約束對父表的含義: 在父表上進行update/delete以更新或刪除在子表中有一條或多條對--應匹配行的候選鍵時,父表的行為取決于:在定義子表的外鍵時指定的-- on update/on delete子句-----------------innodb支持的四種方式---------------------------------------
-----cascade方式 在父表上update/delete記錄時,同步update/delete掉子表的匹配記錄-----外鍵的級聯刪除:如果父表中的記錄被刪除,則子表中對應的記錄自動被刪除--------FOREIGN KEY (charger_id) REFERENCES ClassCharger(id)
ON DELETE CASCADE------set null方式 在父表上update/delete記錄時,將子表上匹配記錄的列設為null-- 要注意子表的外鍵列不能為not nullFOREIGN KEY (charger_id) REFERENCES ClassCharger(id)
ON DELETE SET NULL------Restrict方式 :拒絕對父表進行刪除更新操作(了解)------No action方式 在mysql中同Restrict,如果子表中有匹配的記錄,則不允許對父表對應候選鍵-- 進行update/delete操作(了解)
二、多表查詢
--準備兩張表--company.employee--company.department
create table employee(
emp_idint auto_increment primary key not null,
emp_name varchar(50),
ageint,
dept_idint);
insert into employee(emp_name,age,dept_id) values
('A',19,200),
('B',26,201),
('C',30,201),
('D',24,202),
('E',20,200),
('F',38,204);
create table department(
dept_idint,
dept_name varchar(100)
);
insert into department values
(200,'人事部'),
(201,'技術部'),
(202,'銷售部'),
(203,'財政部');
mysql> select * fromemployee;+--------+----------+------+---------+
| emp_id | emp_name | age | dept_id |
+--------+----------+------+---------+
| 1 | A | 19 | 200 |
| 2 | B | 26 | 201 |
| 3 | C | 30 | 201 |
| 4 | D | 24 | 202 |
| 5 | E | 20 | 200 |
| 6 | F | 38 | 204 |
+--------+----------+------+---------+
6 rows in set (0.00sec)
mysql> select * fromdepartment;+---------+-----------+
| dept_id | dept_name |
+---------+-----------+
| 200 | 人事部 |
| 201 | 技術部 |
| 202 | 銷售部 |
| 203 | 財政部 |
+---------+-----------+
4 rows in set (0.01 sec)
1、多表查詢之連接查詢
1.笛卡爾積查詢
mysql> SELECT *FROM employee,department;-- selectemployee.emp_id,employee.emp_name,employee.age,-- department.dept_name fromemployee,department;+--------+----------+------+---------+---------+-----------+
| emp_id | emp_name | age | dept_id | dept_id | dept_name |
+--------+----------+------+---------+---------+-----------+
| 1 | A | 19 | 200 | 200 | 人事部 |
| 1 | A | 19 | 200 | 201 | 技術部 |
| 1 | A | 19 | 200 | 202 | 銷售部 |
| 1 | A | 19 | 200 | 203 | 財政部 |
| 2 | B | 26 | 201 | 200 | 人事部 |
| 2 | B | 26 | 201 | 201 | 技術部 |
| 2 | B | 26 | 201 | 202 | 銷售部 |
| 2 | B | 26 | 201 | 203 | 財政部 |
| 3 | C | 30 | 201 | 200 | 人事部 |
| 3 | C | 30 | 201 | 201 | 技術部 |
| 3 | C | 30 | 201 | 202 | 銷售部 |
| 3 | C | 30 | 201 | 203 | 財政部 |
| 4 | D | 24 | 202 | 200 | 人事部 |
| 4 | D | 24 | 202 | 201 | 技術部 |
| 4 | D | 24 | 202 | 202 | 銷售部 |
| 4 | D | 24 | 202 | 203 | 財政部 |
| 5 | E | 20 | 200 | 200 | 人事部 |
| 5 | E | 20 | 200 | 201 | 技術部 |
| 5 | E | 20 | 200 | 202 | 銷售部 |
| 5 | E | 20 | 200 | 203 | 財政部 |
| 6 | F | 38 | 204 | 200 | 人事部 |
| 6 | F | 38 | 204 | 201 | 技術部 |
| 6 | F | 38 | 204 | 202 | 銷售部 |
| 6 | F | 38 | 204 | 203 | 財政部 |
+--------+----------+------+---------+---------+-----------+
2.內連接
--查詢兩張表中都有的關聯數據,相當于利用條件從笛卡爾積結果中篩選出了正確的結果。select * from employee,department where employee.dept_id =department.dept_id;--select * from employee inner join department on employee.dept_id =department.dept_id;+--------+----------+------+---------+---------+-----------+
| emp_id | emp_name | age | dept_id | dept_id | dept_name |
+--------+----------+------+---------+---------+-----------+
| 1 | A | 19 | 200 | 200 | 人事部 |
| 2 | B | 26 | 201 | 201 | 技術部 |
| 3 | C | 30 | 201 | 201 | 技術部 |
| 4 | D | 24 | 202 | 202 | 銷售部 |
| 5 | E | 20 | 200 | 200 | 人事部 |
+--------+----------+------+---------+---------+-----------+
3.外連接
--(1)左外連接:在內連接的基礎上增加左邊有右邊沒有的結果select * from employee left join department on employee.dept_id =department.dept_id;+--------+----------+------+---------+---------+-----------+
| emp_id | emp_name | age | dept_id | dept_id | dept_name |
+--------+----------+------+---------+---------+-----------+
| 1 | A | 19 | 200 | 200 | 人事部 |
| 5 | E | 20 | 200 | 200 | 人事部 |
| 2 | B | 26 | 201 | 201 | 技術部 |
| 3 | C | 30 | 201 | 201 | 技術部 |
| 4 | D | 24 | 202 | 202 | 銷售部 |
| 6 | F | 38 | 204 | NULL | NULL |
+--------+----------+------+---------+---------+-----------+
--(2)右外連接:在內連接的基礎上增加右邊有左邊沒有的結果select * from employee RIGHT JOIN department on employee.dept_id =department.dept_id;+--------+----------+------+---------+---------+-----------+
| emp_id | emp_name | age | dept_id | dept_id | dept_name |
+--------+----------+------+---------+---------+-----------+
| 1 | A | 19 | 200 | 200 | 人事部 |
| 2 | B | 26 | 201 | 201 | 技術部 |
| 3 | C | 30 | 201 | 201 | 技術部 |
| 4 | D | 24 | 202 | 202 | 銷售部 |
| 5 | E | 20 | 200 | 200 | 人事部 |
| NULL | NULL | NULL | NULL | 203 | 財政部 |
+--------+----------+------+---------+---------+-----------+
--(3)全外連接:在內連接的基礎上增加左邊有右邊沒有的和右邊有左邊沒有的結果--mysql不支持全外連接 full JOIN--mysql可以使用此種方式間接實現全外連接select * from employee RIGHT JOIN department on employee.dept_id =department.dept_id
UNIONselect * from employee LEFT JOIN department on employee.dept_id =department.dept_id;+--------+----------+------+---------+---------+-----------+
| emp_id | emp_name | age | dept_id | dept_id | dept_name |
+--------+----------+------+---------+---------+-----------+
| 1 | A | 19 | 200 | 200 | 人事部 |
| 2 | B | 26 | 201 | 201 | 技術部 |
| 3 | C | 30 | 201 | 201 | 技術部 |
| 4 | D | 24 | 202 | 202 | 銷售部 |
| 5 | E | 20 | 200 | 200 | 人事部 |
| NULL | NULL | NULL | NULL | 203 | 財政部 |
| 6 | F | 38 | 204 | NULL | NULL |
+--------+----------+------+---------+---------+-----------+
-- 注意 union與union all的區別:union會去掉相同的紀錄
2、多表查詢之復合條件連接查詢
--查詢員工年齡大于等于25歲的部門
SELECT DISTINCT department.dept_name
FROM employee,department
WHERE employee.dept_id=department.dept_id
AND age>25;--以內連接的方式查詢employee和department表,并且以age字段的升序方式顯示selectemployee.emp_id,employee.emp_name,employee.age,department.dept_namefromemployee,departmentwhere employee.dept_id =department.dept_id
order by age asc;
3、多表查詢之子查詢
--子查詢是將一個查詢語句嵌套在另一個查詢語句中。--內層查詢語句的查詢結果,可以為外層查詢語句提供查詢條件。--子查詢中可以包含:IN、NOT IN、ANY、ALL、EXISTS 和 NOT EXISTS等關鍵字-- 還可以包含比較運算符:= 、 !=、> 、
(select dept_id fromdepartment);+--------+----------+------+---------+
| emp_id | emp_name | age | dept_id |
+--------+----------+------+---------+
| 1 | A | 19 | 200 |
| 2 | B | 26 | 201 |
| 3 | C | 30 | 201 |
| 4 | D | 24 | 202 |
| 5 | E | 20 | 200 |
+--------+----------+------+---------+
5 rows in set (0.01sec)-- 2. 帶比較運算符的子查詢-- =、!=、>、>=、
--查詢員工年齡大于等于25歲的部門select dept_id,dept_name fromdepartmentwheredept_id IN
(select DISTINCT dept_id from employee where age>=25);-- 3. 帶EXISTS關鍵字的子查詢--EXISTS關字鍵字表示存在。在使用EXISTS關鍵字時,內層查詢語句不返回查詢的記錄。--而是返回一個真假值。Ture或False--當返回Ture時,外層查詢語句將進行查詢;當返回值為False時,外層查詢語句不進行查詢select * fromemployee
WHERE EXISTS
(SELECT dept_namefrom department where dept_id=203);--department表中存在dept_id=203,Tureselect * fromemployee
WHERE EXISTS
(SELECT dept_namefrom department where dept_id=205);-- Empty set (0.00sec)
ps: create table t1(select * from t2);
三、課后練習
練習一:
1、將所有的課程的名稱以及對應的任課老師姓名打印出來
SELECT cid,cname,tname FROM course LEFT JOIN teacher on course.teacher_id=teacher.tid;
2、查詢學生表中男女生各有多少人
SELECT gender,COUNT(gender) 人數 FROM student GROUP BY gender;
3、查詢物理成績等于100的學生的姓名
SELECT sid,sname FROM student WHERE sid in (SELECT student_id FROM score WHERE course_id=(SELECT cid FROM course WHERE cname='物理') and num=100);
4、查詢平均成績大于八十分的同學的姓名和平均成績
SELECT sname,AVG(num) FROM student,score WHERE student.sid=score.student_id GROUP BY student_id HAVING AVG(num)>80;
5、查詢所有學生的學號,姓名,選課數,總成績
SELECT student_id 學號 ,sname 姓名,COUNT(course_id) 選課數,SUM(num) 總成績 FROM student,score WHERE student.sid=student_id GROUP BY student_id;
6、查詢姓李老師的個數
SELECT COUNT(tname) 姓李老師個數 from teacher WHERE tname like '李%';
7、查詢沒有報李平老師課的學生姓名
SELECT sid,sname FROM student WHERE sid NOT IN (SELECT distinct student_id from score LEFT JOIN student on student_id=student.sid WHERE course_id in (SELECT cid from course,teacher WHERE teacher_id=tid and tname='李平老師'));
mysql> select sid,sname from student where sid not in (SELECT distinct student_id from score where course_id in (SELECT cid from course,teacher WHERE teacher_id=tid and tname='李平老師'));
8、查詢物理課程比生物課程高的學生的學號
SELECT A.student_id FROM
(SELECT * FROM score WHERE course_id=(SELECT cid FROM course WHERE cname='物理'))A
INNER JOIN
(SELECT * FROM score WHERE course_id=(SELECT cid FROM course WHERE cname='生物')) B ON A.student_id = B.student_id WHERE A.num>B.num
9、查詢沒有同時選修物理課程和體育課程的學生姓名
SELECT sid,sname from student WHERE sid NOT IN (SELECT student_id from score WHERE course_id in (2,3) GROUP BY student_id HAVING COUNT(student_id)=2);
10、查詢掛科超過兩門(包括兩門)的學生姓名和班級
SELECT sname,caption FROM student,class WHERE class_id=cid and sid IN (SELECT student_id FROM score WHERE num<60 GROUP BY student_id HAVING COUNT(student_id)>=2);
11 、查詢選修了所有課程的學生姓名
SELECT 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 sid,sname,cname,num FROM ?student RIGHT JOIN (SELECT student_id,cname,num FROM ?score,course WHERE course_id=cid AND course_id in (SELECT cid from course,teacher WHERE teacher_id=tid and tname='李平老師')) ls on ls.student_id=student.sid;
13、查詢選課學生都選修了的課程號和課程名
SELECT cid,cname FROM course WHERE cid =(SELECT course_id from score GROUP BY course_id HAVING COUNT(student_id)=(select count(distinct student_id) from score))
練習二:
14、查詢每門課程被選修的次數
SELECT course_id,cname,COUNT(course_id) 被選課次數 FROM score,course WHERE cid=course_id GROUP BY course_id;
15、查詢只選修了一門課程的學生姓名和學號
SELECT sid,sname FROM student WHERE sid =(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,AVG(num) FROM score,student WHERE student_id =student.sid GROUP BY student_id HAVING AVG(num)>85;
18、查詢生物成績不及格的學生姓名和對應生物分數
SELECT sname,num FROM score,student WHERE student_id=student.sid AND course_id=(SELECT cid FROM course WHERE cname='生物') and num<60;
19、查詢在所有選修了李平老師課程的學生中,這些課程(李平老師的課程,不是所有課程)平均成績最高的學生姓名
SELECT student_id,sname,AVG(num) FROM score,student WHERE student_id=student.sid AND course_id in (SELECT cid FROM course WHERE teacher_id =( SELECT tid FROM teacher WHERE tname like '李平%')) GROUP BY student_id ?ORDER BY AVG(num) DESC LIMIT 1;
20、查詢每門課程成績最好的前兩名學生姓名
21、查詢不同課程但成績相同的學號,課程號,成績
SELECT * FROM score WHERE student_id IN (SELECT student_id FROM score GROUP BY num,student_id HAVING COUNT(student_id)>=2);
22、查詢沒學過“李平”老師課程的學生姓名以及選修的課程名稱;
SELECT * from score WHERE student_id NOT IN (select distinct student_id from score where course_id in (SELECT cid FROM
course WHERE teacher_id =( SELECT tid FROM teacher WHERE tname like '李平%')));
23、查詢所有選修了學號為1的同學選修過的一門或者多門課程的同學學號和姓名;
SELECT sid,sname FROM student WHERE sid IN (SELECT DISTINCT student_id FROM score WHERE course_id IN (SELECT course_id from score WHERE student_id=1) AND student_id!=1);
24、任課最多的老師中學生單科成績最高的學生姓名
SELECT sname FROM student WHERE sid IN (SELECT student_id FROM score,(SELECT course_id,MAX(num) 最大值 FROM score WHERE course_id in (SELECT cid FROM course WHERE teacher_id=(SELECT teacher_id FROM course GROUP BY teacher_id ORDER BY COUNT(cid) DESC LIMIT 1)) GROUP BY course_id HAVING max(num)) A WHERE A.最大值=score.num AND score.course_id=A.course_id);
總結
以上是生活随笔為你收集整理的mysql联表查询多记录显示_数据库:MySQL(多表的表记录的查询)(三)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql分区有好处吗_mysql 分区
- 下一篇: php mysql 博客制作_PHP实现