或許自己的不完美才是最完美的地方,那些讓自己感到不安的瑕疵,最終都會變成自己的特色。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?----------陳長生.
1.介紹
1.1.為什么要進行聯合查詢
? ? ? ? 在數據設計的時候,由于范式的需求,會被分為多個表,但是當我們要查詢數據時,單單一張表的內容是完全不夠的,可能需要查詢的數據覆蓋多個表,那么我們就需要對表進行聯合查詢,也就是將多個表連接在一個表中。
1.2.如何實現聯合查詢
select * from 表1,表2;
select * from student,class;
將所有參與的表取他們的笛卡爾積,并將結果呈現在一張臨時表中。
但是查詢出來的結果有重復的值,我們需要對該表進行過濾
????????可以看到,一個學生表中唐三藏的class_id對應多個班級表中的class_id,意思為原本屬于1班的唐三藏現在屬于1,2,3班,這種結果是不正確的,那我們在查詢的時候就要聲明一個班級只有一個唐三藏,其余學生也是一樣,在MySql中我們稱之為連接條件。
select * from student,class where student.class_id=class.class_id;
這樣才是正確的結果
練習數據:
# 課程表
drop table if exists course;
create table if not exists course(
? course_id bigint primary key auto_increment,
? name varchar(20),
? student_id bigint?
);# 分數表
drop table if exists score;
create table if not exists score(
? score double,
? student_id bigint,
? course_id bigint?
);# 班級表
drop table if exists class;
create table if not exists class(
? class_id bigint primary key auto_increment, ?
? name varchar(20),
? student_id bigint
); ?# 學生表
drop table if exists student;
create table if not exists student(
? id bigint primary key auto_increment,
? name varchar(20),
? sno bigint,
? age int,
? gender int,
? enroll_date varchar(20),
? class_id bigint
);
# 課程表
insert into course (name)values ('Java'), ('C++'), ('MySQL'), ('操作系統'), ('計算機網絡'), ('數據結構');
# 班級表
insert into class(name) values ('Java001班'), ('C++001班'), ('前端001班');
# 學生表
insert into student (name, sno, age, gender, enroll_date, class_id) values?
('唐三藏', '100001', 18, 1, '1986-09-01', 1),
('孫悟空', '100002', 18, 1, '1986-09-01', 1),
('豬悟能', '100003', 18, 1, '1986-09-01', 1),
('沙悟凈', '100004', 18, 1, '1986-09-01', 1),
('宋江', '200001', 18, 1, '2000-09-01', 2),
('武松', '200002', 18, 1, '2000-09-01', 2),
('李逹', '200003', 18, 1, '2000-09-01', 2),
('不想畢業', '200004', 18, 1, '2000-09-01', 2);
# 成績表
insert into score (score, student_id, course_id) values
(70.5, 1, 1),(98.5, 1, 3),(33, 1, 5),(98, 1, 6),
(60, 2, 1),(59.5, 2, 5),
(33, 3, 1),(68, 3, 3),(99, 3, 5),
(67, 4, 1),(23, 4, 3),(56, 4, 5),(72, 4, 6),
(81, 5, 1),(37, 5, 5),
(56, 6, 2),(43, 6, 4),(79, 6, 6),
(80, 7, 2),(92, 7, 6);
2.內連接
1.select * from 表1 別名1,表2 別名2 where 連接條件 and 連接條件;(常用*)
2.select * from 表1 別名1,join 表2?別名2 on 連接條件 and 連接條件;?
2.1.查找武松的信息
select * from student s,class c where s.class_id=c.class_id and s.name='武松';
?select * from student s join class c on s.class_id=c.class_id and s.name='武松';
2.2.查詢所有同學每門課的成績以及同學的個人信息
select * from student s, score sc, course c?
where
s.id=sc.student_id
and
c.course_id=sc.course_id;
2.3.查詢所有同學的總成績以及同學的個人信息
select s.name,sum(sc.score) from student s,score sc?
where
s.id=sc.student_id
group by s.id;
3.外連接
外連接分別為左連接,右連接,全連接(MySql不支持全連接,所以這邊就不講了)
左連接:以左表為基礎,將右表的數據插入左表中,若左表中有右表沒有的數據,則插入的數據顯示為NULL。
左連接:以右表為基礎,將左表的數據插入右表中,若右表中有左表沒有的數據,則插入的數據顯示為NULL。
全連接:左表與右表的結合
注:不管是左表還是右表,MySql在執行的過程中都會轉換為左連接,所以我們一般使用左連接
-- 左連接
select * from 左表 left join 右表 on 連接條件;
-- 右連接
select * from 左表 left join 右表 on 連接條件;
3.1.查詢沒有參加考試的同學信息
select * from student s(左表)?
left join
score sc (右表)
on?
s.id=sc.student_id(連接條件)?
where?
sc.score is null(判斷條件);
3.2.查詢沒有學?的班級
select * from class c(左表)?
left join?
student s(右表)
on?
s.class_id=c.class_id(連接條件)?
where
s.id is nul(判斷條件)l;
4.自連接
自連接就是自己與自己取笛卡爾積,可以把行轉換為列,并在查詢時過濾,就可以實現行與行之間的比較(MySql本身不支持行與行之間的比較,但是我們可以使用自連接實現)
select * from 表1 別名1,表1 別名2;
4.1.顯示所有"MySQL"成績?"JAVA"成績?的成績信息
select?s1.* from?
score s1,
score s2,
course c1,
course c2(將成績表與課程表進行自連接)
where?
s1.student_id=s2.student_id
and?
s1.course_id=c1.course_id
and?
s2.course_id=c2.course_id(過濾)
and?
c1.name='MySQL'
and?
c2.name='JAVA'
and?
s1.score>s2.score;(根據題目要求進行條件判斷)
5.子查詢
子查詢也叫嵌套查詢,可以把一個查詢的結果給另外一個查詢語句當作條件
select * from 表名? where 條件=(select 條件 from 表名 ...);
5.1.單行子查詢
5.1.1.查詢與"不想畢業"同學的同班同學
-- 正常查詢 (先查找不想畢業所在班級再通過班級找到同班同學)
select class_id from student where name='不想畢業' ;
select name from student where class_id=2;
-- 單行子查詢(查詢名字后,直接通過子查詢判斷class_id條件)
select name from student ?
where
class_id=(select class_id from student where name='不想畢業' );
5.2.多行子查詢
嵌套查詢可以返回多行數據 ,使用in關鍵詞
select * from 表名? where 條件? in(select 條件 from 表名 ...);
5.2.1.查詢"MySQL"或"Java"課程的成績信息
--正常查詢
select course_id from course where name ='MySQL' or name='Java';
select * from score where course_id=1 or course_id=3 ;
--多行子查詢
select * from score
where
course_id
in
(select course_id from course where name='MySQL' or name='Java'(多行數據));
5.3.多列子查詢
5.3.1.查詢重復錄?的分數
先插入數據
insert into score values (70.5,1,1);
insert into score values (98.5,1,3);
insert into score values (99,3,5);
-- 多列子查詢
select * from score where?
(score,student_id,course_id)
?in
? (select?
?score,student_id,course_id?
?from score
?group by?
?score,student_id,course_id?
?having count(*)>1);
5.4.在from子句中使用子查詢
5.4.1.查詢所有比"Java001班"平均分?的成績信息
-- 先查平均分成績
select avg(sc.score) score from student st, class c , score sc
where
st.class_id=c.class_id
and?
c.name='JAVA001班'
and?
st.id=sc.student_id;--再查大于平均分
select * from score s,(select avg(sc.score) score from student st, class c , score sc
where
st.class_id=c.class_id
and?
c.name='JAVA001班'
and?
st.id=sc.student_id) temp
where?
s.score>temp.score;
6.合并查詢
????????合并查詢分為 union 與union all,也就是將兩張表的數據合并為一張存在臨時表中,當前提是兩張表的列信息一樣。
6.1.union(去重)
select * from 表1 別名1?union select * from 表2?別名2;
6.2.union all(不去重)
select * from 表1 別名1?union all select * from 表2?別名2;
7.插入查詢結果
????????將一張表的數據插入到另一張表中,當前提是兩個表的列信息一樣。????????
insert into 新表(列..)select ...
7.1.將student表中C++001班的學?復制到student1表中
-- 先創建新學生表(與原本的學生表列信息相同)
?create table new_student like student;
--復制
insert into?
new_student (name,sno,gender,enroll_date,class_id)
select?
s.name,s.sno,s.gender,s.enroll_date,s.class_id?
from?
student s,class c?
where?
s.class_id=c.class_id?
and?
c.name='C++001班' ;