表關系判斷:
表關系分類:
1.一對多
2.多對多
3.一對一
4.沒有關系
表關系的判斷:
思想:換位思考
一對多:
外鍵字段建在多的一方。
1.以員工表與部門表為例:
1.先站在員工表角度
問:一個員工能否對應多個部門
答:不可以
2.再站在部門表角度
問:一個部門能否對應多名員工
答:可以
結論:兩邊一個可以,一個不可以,那麼表關系就是一對多。
SQL語句實作:
1.先建立基本字段
2.在考慮外鍵字段
create table emp(
id int primary key auto_increment,
emp_name varchar(32),
emp_salary int,
dep_id int,
foreign key(dep_id) references dep(id)
);
create table dep(
id int primary key auto_increment,
dep_name varchar(32),
dep_desc varchar(64)
);
注意:
1.在建立表時先建立被關聯的表(沒有外鍵字段的表)。
2.在錄入資料的時候,先錄入被關聯表的資料。
3.修改或删除被關聯的資料,沒法做修改。
級聯更新級聯删除SQL實作:
create table emp(
id int primary key auto_increment,
emp_name varchar(32),
emp_salary int,
dep_id int,
foreign key(dep_id) references dep(id)
on update cascade #級聯更新
on delete cascade #級聯删除
);
create table dep(
id int primary key auto_increment,
dep_name varchar(32),
dep_desc varchar(64)
);
多對多
針對多對多關系,外鍵字段并不會建在任何一張表,而是單獨開設一張新表,單獨存儲
SQL實作:
create table book(
id int primary key auto_increment,
title varchar(32),
price float(8,2)
);
create table book(
id int primary key auto_increment,
title varchar(32),
price float(8,2)
);
create table booktoauthor(
id int primary key auto_increment,
author_id int,
foreign key(author_id) refrenxes author(id)
on update cascade
on delete cascade,
book_id int,
foreign key(book_id) references book(id)
on update cascade
on delete cascade
);
一對一
以使用者表與使用者詳情表為例
先站在使用者表角度
問:一名使用者能否對應多個使用者詳情
答:不可以
再站在使用者詳情表角度:
問:一個使用者詳情是否能對應多名使用者
答: 不可以
針對一對一關系,外鍵字段建在任何一方都可以,但是推薦你建立在查詢頻率較高的表中。
SQL實作:
create table userinfo(
id int primary key auto_increment,
name varchar(32),
age int,
detail_id int unique, #設定唯一索引建立一對一關系
foreign key(detail_id) references userinfo_detail(id)
on update cascade
on delete cascade
);
查詢關鍵字
1.select
用來指定表的字段資料
select * from emp;
select id, name from emp;
在工作中一般很少使用*。
2.from
後面跟需要查詢的表名。
3.where 篩選資料
1.查詢id大于等于3,小于等于6的資料
select id ,name from emp where id >=3 and id <= 6;
select id ,name from emp where id between 3 and 6;
2.查詢薪資是20000或18000或17000的資料
select * from emp where salary = 20000 or salary = 18000 or salary = 17000;
select * from emp where salary in (20000,18000,17000);
模糊查詢:
關鍵字 like
關鍵符号:
%:比對任意個數的任意字元
_:比對單個個數的任意字元
3.查詢姓名中帶有字母o的員工姓名和薪資
select name,salary from emp where name like ‘%o%’;
4.查詢姓名中有四個字元組成的員工姓名和薪資
select name,salary from emp where name like ‘____’;
select name,salary from emp where char_length(name) = 4;
5.查詢id小于3或者大于6的資料
select * from emp where id not between 3 and 6;
6.查詢薪資不在20000,18000,17000範圍的資料
select * from emp where salary not in (20000,18000,17000);
7.查詢崗位描述為空的員工與崗位名 針對null不能用等号,隻能用is
select name,post from emp where post_comment is NULL;
select name,post from emp where post_comment is not NULL;
4.group by 分組
分組
将單個單個的個體按照指定條件分成一個個整體。
分組之後預設隻能擷取分組的依據,其他字段無法在直接擷取(可以間接擷取)
但是5.6需要手動開啟嚴格模式
set global sql_mode = ‘STRICT_TRANS_TABLES,PAD_CHAR_TO_FULL_LENGTH,ONLY_FULL_GROUP_BY’
聚合函數
分組之後頻繁需要使用的
max 最大值
min 最小值
sum 求和
count 計數
avg 平均值
1.每個部門的最高工資
select post,max(salary) from emp group by post;
2.每個部門的最低工資
select post,min(salary) from emp group by post;
3.每個部門的平均薪資
select post,avg(salary) from emp group by post;
4.每個部門的人數
select post,count(id) from emp group by post;
5.每個部門的月工資總和
select post,sum(salary) from emp group by post;
可以使用as起别名,也可以給表起别名
select post as ‘部門’,sum(salary) as ‘總和’ from emp group by post;
檢視分組之後的部門名稱和每個部門下所有的員工姓名
group_count() 擷取分組以外的字段資料,并且支援拼接操作
select post,group_concat(name) from emp group by post;
select post,group_concat(name,’:’,salary) from emp group by post;
concat() 未分組之前使用的拼接功能
select concat(name,’:’,sex) from emp;
concat_ws()
select concat_ws(’:’,name,sex,salary,age) from emp;
group_concat(name,’:’,salary) 擷取分組以外的字段資料,
5.having 過濾
功能上having與where是一樣的,但是使用位置上有所不同
where在分組之前使用,having在分組之後使用。
舉例:
統計各部門年齡在30歲以上的員工
1.先篩選出所有30歲以上的員工
select * from emp where age>30;
2.然後再按照部門分組
select post,avg(salary) from emp where age>30 group by post;
3.分組之後做過濾操作
select post,avg(salary) from emp
where age>30
group by post
having avg(salary)>10000;
6.distinct 去重
帶有主鍵的資料肯定無法去重
select distinct age from emp;
7.order by 排序
預設升序 關鍵字 asc
降序排序 關鍵字 desc
select * from emp order by salary desc;
指定多個字段
select * from emp order by age desc,salary asc;
統計各部門年齡在20歲以上的員工的平均工資,并且保留平均高工資大于1000的部門,然後對平均工資進行排序。
不在代碼行敲的代價,未知原因報錯就是不行,後來也不知道為什麼就又好了,神。
select post,avg(salary) from emp
where age>20
group by post
having avg(salary)>1000
order by avg(salary) desc;
在代碼行敲的就可以。
select post,avg(salary) from emp
where age>20
group by post
having avg(salary)>1000
order by avg(salary) desc;
8.limit 分頁
用來限制資料的顯示:
select * from emp limit 5,5;
# 查詢工資最高的人的詳細資訊,先按照工資排序,然後限制展示條數
select * from emp order by salary desc limit 1;
9.regexp 正則
正規表達式 用一些特殊複合的組合篩選出符合條件的資料
select * from emp where name regexp '^j.*(n|y)$';
# '^j.*(n|y)$' j開頭 中間無所謂 n或者y結尾
多表查詢的思想
1.子查詢
分布解決問題
将一條SQL語句的查詢結果用括号括起來,作為另一條語句的查詢條件。
select * from dep where id in (select dep_id from emp where name=‘jason’)
2.連表操作
前戲(了解)
select * from emp,dep
基于上表篩選資料
為了避免字段沖突可以在字段名前加表名明确。
select * from emp,dep where emp.dep_id = dep.id
現将所有需要用到的表拼接到一起(一張表)
然後就是轉換成單表查詢
連表操作:
inner join 内連接配接 連接配接公共部分
select * from emp inner join dep on emp.dep_id=dep.id;
left join 左連接配接 以左表為基準展示所有資料,沒有的null填充
select * from emp left join deo on emp.dep_id=dep.id;
right join 右連接配接 以右表為基準展示所有資料,沒有的null填充
select * from emp right join deo on emp.dep_id=dep.id;
union 全連接配接 以所有表為基準展示所有資料,沒有的null填充
select * from emp left join deo on emp.dep_id=dep.id
union
select * from emp right join deo on emp.dep_id=dep.id;
建議:在書寫SQL語句的時候一定不要想着一次成功,寫一點看一點再寫一點,慢慢拼湊起來
表字段操作的補充
1.添加表字段
alter table t_name add age int; #預設尾部追加
alter table t_name add gender enum(‘male’,‘female’) after age; #指定追加位置
alter table t_name add 字段名 字段類型 first #追加在開頭
2.修改字段
modify隻能改字段資料類型完整限制,不能改字段名,但是change可以
ALTER TABLE 表名 MODIFY 字段名 資料類型 [完整性限制條件…];
ALTER TABLE 表名 CHANGE 舊字段名 新字段名 資料類型 [完整性限制條件…];
3.删除字段
ALTER TABLE 表名 DROP 字段名;