1. 程式人生 > >Python學習--day40-mysql資料庫查詢

Python學習--day40-mysql資料庫查詢

一、表的結構操作

# 1.表的詳細操作
​
create table nt like ot; # 只複製表的結構包括約束
​
create table nt select * from ot where 1=2; # 複製表結構, 但不復制鍵(相關)的約束
​
truncate t1; 清空表, 自增記錄會被重置
​
# 2.表中欄位的詳細操作
​
alter table t1 add ntag1 型別[(寬度) 約束], ..., add ntag2 型別[(寬度) 約束];
alter table t1 add ntag 型別[(寬度) 約束] first;
alter table t1 add ntag 型別[(寬度) 約束] after otag;
​
alter table t1 modify ntag 型別[(寬度) 非鍵約束] first; 
# 移動到最前 alter table t1 modify ntag 型別[(寬度) 非鍵約束] after otag; # 移動到otag後 ​ ​ # 3.使用者管理 grant all on db1.* to [email protected] identified by 'owen'; # (建立使用者)設定許可權 ​ ​ # 4.表關係 create table 從表( id int primary key auto_increment, ... 主表_id int, # 只是在從表中起了一個名字, 該名字和主表主鍵對應,所有起了個見名知義的名字 foreign key(主表_id) references 主表(唯一欄位名id) on update cascade on delete cascade );
# 作者與作者詳情 # 外來鍵直接影響資料庫效率, 但會提高資料的完整性(安全), 一般首先效率, 因為安全可以通過其他方式來處理

 



二、表中的資料操作

# 1.完整語法的增刪改
# 2.單表查詢 => 查詢條件
# 3.多表查詢

 

1、增語法

'''
1.所有資料按順序插入
insert [into] 表名 values (值1, ..., 值n)[, ..., (值1, ..., 值n)];
​
2.指定欄位匹配插入,可以任意順序
insert [into] 表名(欄位2, 欄位1, ..., 欄位n) values (值2, 值1, ..., 值n)[, ..., (值2, 值1, ..., 值n)];
​
3.插入查詢結果
insert [into] 表1(欄位1, ..., 欄位n) select 欄位1, ..., 欄位n from 表2 [條件];
'''# eg: 1 create table t1( id int auto_increment, x int, y int, primary key(id) ); insert t1 values (1, 2, 3), (2, 20, 30); # 按順序插入 insert into t1(y, x) values (300, 200); # 按規定欄位順序指定插入 ​ create table nt1 like t1; # 複製表即完整結構 insert into nt1 select * from t1; # 複製所有資料 ​ create table tt1( x int, z int ); insert into tt1 values (999, 888); insert into nt1(x) select x from tt1; # 將tt1中指定欄位插入到nt1中指定的欄位 insert into nt1(x, y) select x,z from tt1; # tt1x及z欄位的結果賦值給nt1中x,y欄位

 

 

2、刪語法

1.會記錄自增資訊,操作會被日誌記錄,效率低
delete from 表名 [條件];
delete from t1; # 沒有條件的情況下是清空所有資料, 但會記錄自增資訊
insert into t1(x, y) values(6, 66);
​
2.清空表,會重置自增資訊
truncate table 表名;
truncate table nt1;
insert into nt1(x, y) values(6, 66); 

3、改語法

update 表名 set 欄位1=值1[, ..., 欄位n=值n] [條件]
update tt1 set x=666; # 如果無條件, 則全改
update tt1 set x=777, z=555 where z<888; # 只修改滿足條件的行

 

4、 查語法

'''
select [distinct] 欄位1 [as 別名], ..., 欄位n [as 別名] from [庫名.]表名
                    [
                    where 約束條件
                    group by 分組依據
                    having 過濾條件
                    order by 排序的欄位
                    limit 限制顯示的條數
                    ];
注:
1.查表中所有欄位用*表示
2.條件的書寫規則嚴格按照語法順序書寫,可以預設,但不可以錯序
3.約束條件的流程:from -> where -> group by -> having -> distinct -> order by -> limit
4.欄位可以起別名
5.欄位可以直接做運算 select age + 1 'new_age' from emp;
6.分組後的條件均可以使用聚合函式
''''''
3.
def from():
    return "查詢的檔案"
def where(file):
    return "條件篩選後的結果"
def group_by(res):
    return "分組後的結果"
def having(res):
    return "再次過濾後的結果"
def distinct(res):
    return "去重後的結果"
def order_by(res):
    return "排序後的結果"
def limit(res):
    return "限制條數後的結果"
​
def select(from=from, where=null, ..., limit=null):
    file = from()
    res = where(file) if where else file
    res = group_by(res) if group_by else res
    ...
    res = limit(res) if limit else res
    
    return res
select(where=where, group_by=group_by)
'''

5、單表資料

CREATE TABLE `emp`  (
  `id` int(0) NOT NULL AUTO_INCREMENT,
  `name` varchar(10) NOT NULL,
  `gender` enum('','','未知') NULL DEFAULT '未知',
  `age` int(0) NULL DEFAULT 0,
  `salary` float NULL DEFAULT 0,
  `area` varchar(20) NULL DEFAULT '中國',
  `port` varchar(20) DEFAULT '未知',
  `dep` varchar(20),
  PRIMARY KEY (`id`)
);
​
INSERT INTO `emp` VALUES 
    (1, 'yangsir', '', 42, 10.5, '上海', '浦東', '教職部'),
    (2, 'engo', '', 38, 9.4, '山東', '濟南', '教學部'),
    (3, 'jerry', '', 30, 3.0, '江蘇', '張家港', '教學部'),
    (4, 'tank', '', 28, 2.4, '廣州', '廣東', '教學部'),
    (5, 'jiboy', '', 28, 2.4, '江蘇', '蘇州', '教學部'),
    (6, 'zero', '', 28, 8.8, '中國', '黃浦', '諮詢部'),
    (7, 'owen', '', 28, 8.8, '安徽', '宣城', '教學部'),
    (8, 'alex', '', 40, 6.3, '北京', '東城', '教學部'),
    (9, 'ying', '', 36, 1.2, '安徽', '蕪湖', '諮詢部'),
    (10, 'kevin', '', 36, 5.8, '山東', '濟南', '教學部'),
    (11, 'monkey', '', 28, 1.2, '山東', '青島', '教職部'),
    (12, 'san', '', 30, 9.0, '上海', '浦東', '諮詢部'),
    (13, 'san1', '', 30, 6.0, '上海', '浦東', '諮詢部'),
    (14, 'san2', '', 30, 6.0, '上海', '浦西', '教學部');

 

 

6、簡單查詢

select concat(area, '-', port) as '家鄉' from emp; # 上海-浦東... 屬於 起的別名 家鄉 列
select concat_ws("-", name, area, port) '資訊' from emp; # 以"-"字元拼接後面的所有欄位
select upper(name) [as] 'name', gender, age from emp; # 可以指定多個欄位
+---------+--------+------+
| name    | gender | age  |
+---------+--------+------+
| YANGSIR | 男     |   42 |
| ENGO    | 男     |   38 |
| KEVIN   | 男     |   36 |
+---------+--------+------+
select name, ceil(salary), floor(salary), round(salary) from emp where name='kevin'; # 數學函式
+-------+--------------+---------------+---------------+
| name  | ceil(salary) | floor(salary) | round(salary) |
+-------+--------------+---------------+---------------+
| kevin |            6 |             5 |             6 |
+-------+--------------+---------------+---------------+# 去重前提: 所查所有欄位的綜合結果完全相同, 才認為是重複的, 只保留重複中的一行資料
select distinct area from emp;  # 顯示emp表中的area列中不重複的值
select distinct area, port from emp; # 顯示emp表中的area和port列都不重複的值

 

 

7、常用函式

concat(欄位1,...,欄位n):完成欄位的拼接
concat_ws(x, 欄位1,...,欄位n):完成欄位的拼接,x為連線符
lower():小寫
upper():大寫
ceil():向上取整
floor():向下取整
round():四捨五入 

8、where條件

1.比較運算子
= | < | > | <= | >= | !=
select * from emp where area!="上海";
​
2.區間運算子
between 10 and 20:10~20
in(10, 20, 30):10或20或30
select * from emp where id between 10 and 14; # [10, 14], 閉合區間,包含10和14, 4行資料 
+----+--------+--------+------+--------+--------+--------+-----------+
| id | name   | gender | age  | salary | area   | port   | dep       |
+----+--------+--------+------+--------+--------+--------+-----------+
| 10 | kevin  | 男     |   36 |    5.8 | 山東    | 濟南    | 教職部     |
| 12 | san    | 男     |   30 |      9 | 上海    | 浦東    | 諮詢部     |
| 13 | san1   | 男     |   30 |      6 | 上海    | 浦東    | 諮詢部     |
| 14 | san2   | 男     |   30 |      6 | 上海    | 浦西    | 教學部     |
+----+--------+--------+------+--------+--------+--------+-----------+
​
select * from emp where id in(2, 4, 6, 8); # 分離的區間,2,4,6,8都會被顯示
+----+------+--------+------+--------+--------+--------+-----------+
| id | name | gender | age  | salary | area   | port   | dep       |
+----+------+--------+------+--------+--------+--------+-----------+
|  2 | engo | 男     |   38 |    9.4 | 山東    | 濟南    | 教學部     |
|  4 | tank | 女     |   28 |    2.4 | 廣州    | 廣東    | 教學部     |
|  6 | zero | 男     |   28 |    8.8 | 中國    | 黃浦    | 諮詢部     |
|  8 | alex | 男     |   40 |    6.3 | 北京    | 東城    | 教學部     |
+----+------+--------+------+--------+--------+--------+-----------+3.邏輯運算子
and | or | not
select * from emp where area="山東" and port="濟南";
+----+-------+--------+------+--------+--------+--------+-----------+
| id | name  | gender | age  | salary | area   | port   | dep       |
+----+-------+--------+------+--------+--------+--------+-----------+
|  2 | engo  | 男     |   38 |    9.4 | 山東    | 濟南    | 教學部    |
| 10 | kevin | 男     |   36 |    5.8 | 山東    | 濟南    | 教學部    |
+----+-------+--------+------+--------+--------+--------+-----------+4.相似運算子
like '_owen%':模糊匹配字串owen,_表示一個字元,%表示任意字元
# 匹配的欄位為en,想得到的結果為owen
select * from emp where name like '__en%'; # 在en前可以出現2個任意字元, 之後可以出現0或多個任意字元
​
​
# 需求:
# 查詢姓名有數字的員工資訊
 此需求需要用到正則表示式,分析如下:

 

 

正則匹配

# why: like完成模糊匹配, 但功能侷限, 可以模糊個數, 但不能模糊型別, 正則可以完成型別及個數的模糊匹配
'''
語法:欄位 regexp '正則表示式'
注:只支援部分正則語法
'''
# 完成需求:
select * from emp where name regexp '.*[0-9]+.*';
+----+------+--------+------+--------+--------+--------+-----------+
| id | name | gender | age  | salary | area   | port   | dep       |
+----+------+--------+------+--------+--------+--------+-----------+
| 13 | san1 | 男     |   30 |      6 | 上海    | 浦東    | 諮詢部     |
| 14 | san2 | 男     |   30 |      6 | 上海    | 浦西    | 教學部     |
+----+------+--------+------+--------+--------+--------+-----------+

 

9、group by 分組

'''
分組:根據欄位相同值形成不同的類別,不明確分組其實整個表就為一個預設大組
原因:把以值共性得到的類別作為考慮單位,不再關係單條記錄,而且一組記錄
​
結果:只能考慮組內多條資料的聚會結果(聚合函式結果),分組的欄位同樣是聚合結果,如:組內的最大最小值
sql_mode=ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
​
聚合函式:
max():最大值
min():最小值
avg():平均值
sum():和
count():記數
group_concat():組內欄位拼接,用來檢視組內其他欄位
​
eg:1
每個部門的平均薪資
select dep, avg(salary) '平均薪資' from emp group by dep;
+-----------+-------------------+
| dep       | 平均薪資           |
+-----------+-------------------+
| 諮詢部    | 6.250000059604645  |
| 教學部    | 5.512500047683716  |
| 教職部    | 5.850000023841858  |
+-----------+-------------------+
​
eg:2
每個部門都有哪些人
select dep, group_concat(name) from emp group by dep;  #group_concat是固定的語句,不可修改
+-----------+--------------------------------------------+
| dep       | group_concat(name)                         |
+-----------+--------------------------------------------+
| 諮詢部    | san1,san,ying,zero                          |
| 教學部    | san2,kevin,alex,owen,jiboy,tank,jerry,engo  |
| 教職部    | monkey,yangsir                              |
+-----------+--------------------------------------------+
​
需求:
各性別中附屬於教學部的最高薪資
select max(salary) '最高薪資', gender from emp where dep='教學部' group by gender;
+--------+--------------+
| gender | 最高薪資      |
+--------+--------------+
| 男     |          9.4 |
| 女     |            3 |
+--------+--------------+
思考:
想知道需求中員工的姓名 => 子查詢
上方結果: 男的最高薪資對應的人名, 女的最高薪資對應的人名
# select group_concat(name), max(salary) '最高薪資', gender from emp where dep='教學部' group by gender; 錯誤
​
select name from emp where salary in (select max(salary) '最高薪資' from emp where dep='教學部' group by gender);
+----+-------+--------+------+--------+--------+-----------+-----------+
| id | name  | gender | age  | salary | area   | port      | dep       |
+----+-------+--------+------+--------+--------+-----------+-----------+
|  2 | engo  | 男     |   38 |    9.4 | 山東    | 濟南       | 教學部     |
|  3 | jerry | 女     |   30 |      3 | 江蘇    | 張家港     | 教學部     |
+----+-------+--------+------+--------+--------+-----------+-----------+
'''
注:當我在表中插入:insert into emp(id,name,gender,age,salary,area,port,dep) values(15, 'per, '',18, 3.0, '江蘇', '張家港', '諮詢部');時,此時在執行上訴mysql語句,得到的結果會變為:
+----+-------+--------+------+--------+--------+-----------+-----------+
| id | name  | gender | age  | salary | area   | port      | dep       |
+----+-------+--------+------+--------+--------+-----------+-----------+
|  2 | engo  | 男     |   38 |    9.4 | 山東   | 濟南       | 教學部      |
|  3 | jerry | 女     |   30 |      3 | 江蘇   | 張家港      | 教學部     |
| 15 | per   | 女     |   18 |      3 | 江蘇   | 張家港      | 諮詢部     |
+----+-------+--------+------+--------+--------+-----------+-----------+
很明顯與我們的意願相悖,但是也具有一定的參考度。
​
1. 14條資料部門有3個, 並且每個部分有多條記錄, 可以作為分組依據, 同理, 性別也可以
# select * from emp group by dep; # 非分組安全模式下, 可以查詢非聚合結果, 顯示的是第一條記錄, 沒有意義, 分組安全模式下不能查詢非聚合結果的欄位
result:'''ERROR 1055 (42000): 'kt1.emp.id' isn't in GROUP BY ''' # select後面的查詢內容必須要是分組欄位或者聚合函式得到的結果,否則就會報錯。
​
select dep from emp group by dep;
+-----------+
| dep       |
+-----------+
| 諮詢部     |
| 教學部     |
| 教職部     |
+-----------+2. 如果就像以姓名進行分組, 可以, 但沒多大意義, 原因name值基本上都不相同, 以組考慮會導致組內大多隻要一條記錄(自成一組), 組的利用就不是很強烈, 此類分組是無意義的
select name from emp group by name; # 可以分組, 意義不大
​
考慮的三個問題: 以什麼分組(相同資料較多的欄位) 分組後的考慮單位(組並非組內的每一條記錄) 可以查詢的結果(當前分組的欄位及聚合函式形成的聚合結果)

解決分組中思考題的過程

# res = select max(salary) '最高薪資', gender from emp where dep='教學部' group by gender;
# select name from emp where (salary 跟 res作比較)
# 一個查詢依賴於另一個查詢的結果 => 一個查詢的結果作為另外一個查詢的條件 => 子查詢

10、子查詢


子查詢:將一條查詢結果作為另外一條查詢的條件
語法:一條select語句用()包裹得到的結果作為另一條select語句的條件
# 偽sql: select * from emp where salary =|in (select salary from emp where 條件)
​
單行子查詢:
子查詢語句的結果為一行資料,可以結合 = | < | > | <= | >= | != 運算子來完成父查詢
select salary from emp where salary > 10; # => 作為子查詢
# 查詢姓名,性別.地區,基於薪資大於10的結果的查詢結果
​
eg: 1
select name, gender, area from emp where salary = (select salary from emp where salary > 10);
​
多行子查詢:
子查詢語句的結果為多行資料,可以結合 in | all | any 運算子來完成父查詢
in:任意單一值,一次只能考慮子查詢中的一個結果
all:全部值,將子查詢結果作為一個整體考慮
any:任意多個值:子查詢的每一個結果都可以作為參考依據
​
eg: 2
# 子查詢的結果 (9.4, 3)
select name from emp where salary in (select max(salary) '最高薪資' from emp where dep='教學部' group by gender);
+-------+
| name  |
+-------+
| engo  |
| jerry |
+-------+
# 遍歷14條資料, 14條資料的salary在(9.4, 3)區域中,就可以完成匹配, 結果為兩條(9.4和3那兩條)
​
select * from emp where salary < all(select max(salary) '最高薪資' from emp where dep='教學部' group by gender);
+----+--------+--------+------+--------+--------+--------+-----------+
| id | name   | gender | age  | salary | area   | port   | dep       |
+----+--------+--------+------+--------+--------+--------+-----------+
|  4 | tank   | 女     |   28 |    2.4 | 廣州   | 廣東    | 教學部     |
|  5 | jiboy  | 男     |   28 |    2.4 | 江蘇   | 蘇州    | 教學部     |
|  9 | ying   | 女     |   36 |    1.2 | 安徽   | 蕪湖    | 諮詢部     |
| 11 | monkey | 女     |   28 |    1.2 | 山東   | 青島    | 教職部     |
+----+--------+--------+------+--------+--------+--------+-----------+
# 遍歷14條資料, salary要小於(9.4, 3)中的每一個, 反映就是小於3, 結果為薪資1.2,2.4的那四條資料
​
select * from emp where salary > any(select max(salary) '最高薪資' from emp where dep='教學部' group by gender);
+----+---------+--------+------+--------+--------+--------+-----------+
| id | name    | gender | age  | salary | area   | port   | dep       |
+----+---------+--------+------+--------+--------+--------+-----------+
|  1 | yangsir | 男     |   42 |   10.5 | 上海   | 浦東    | 教職部    |
|  2 | engo    | 男     |   38 |    9.4 | 山東   | 濟南    | 教學部    |
|  6 | zero    | 男     |   28 |    8.8 | 中國   | 黃浦    | 諮詢部    |
|  7 | owen    | 男     |   28 |    8.8 | 安徽   | 宣城    | 教學部    |
|  8 | alex    | 男     |   40 |    6.3 | 北京   | 東城    | 教學部    |
| 10 | kevin   | 男     |   36 |    5.8 | 山東   | 濟南    | 教學部    |
| 12 | san     | 男     |   30 |      9 | 上海   | 浦東    | 諮詢部    |
| 13 | san1    | 男     |   30 |      6 | 上海   | 浦東    | 諮詢部    |
| 14 | san2    | 男     |   30 |      6 | 上海   | 浦西    | 教學部    |
+----+---------+--------+------+--------+--------+--------+-----------+
# 遍歷14條資料, salary大於9.4或大於3的資料均滿足條件, 結果就是刨除小於等於3的那幾條資料

11、having 篩選

 
 
 
why:完成在分組之後的篩選
注意:having條件是實現聚合結果層面上的篩選 => 拿聚會結果完成判斷
​
需求:
1.各部門的平均薪資
select dep, avg(salary) '平均薪資' from emp group by dep;
​
2.平均薪資大於6w的部門(部門與部門的平均薪資)
解決: 以dep進行分組, 以avg(salary)作為判斷條件(篩選)
select dep, avg(salary) '平均薪資' from emp group by dep having avg(salary) > 6;
+-----------+-------------------+
| dep       | 平均薪資           |
+-----------+-------------------+
| 諮詢部    | 6.250000059604645  |
+-----------+-------------------+# 總結: having通過聚合函式結果完成篩選
select max(salary) from emp having max(salary) > 9.4;
+-------------+
| max(salary) |
+-------------+
|        10.5 |
+-------------+
# 雖然沒有明確書寫group by, 但在having中使用了聚合函式,所以該查詢就將整個表當做一個預設大表來考慮,所以查詢的欄位只能為聚合函式的結果

 

 

12、order by 排序

'''
why:完成排序
注意:可以使用聚合函式,哪怕沒有明確group by
​
升序 | 降序:asc | desc
eg:order by age desc => 按照年齡降序
select * from emp order by age desc;
​
​
需求:
將部門按照部門平均工資降序方式排序
select dep, avg(salary) from emp group by dep order by avg(salary) desc;
''' 

13、limit 限制

'''
why:限制最終結果的資料行數
注意:limit只與數字結合使用
​
應用:
limit 1:只能顯示一行資料
limit 6,5:從第6+1行開始顯示5條資料(索引從0開始)
​
select * from emp limit 1;
select * from emp limit 6,5;
​
需求:
獲得薪資最高的人的一條資訊
select * from emp order by salary desc limit 1;
'''