進擊のpython
數據庫——單表查詢
數據庫在使用的時候,更多的是查看數據,而學會了外鍵之后,查詢就已經不僅僅是針對單個表的操作了
同時,對於單表的查詢要求也是越來越高,而基於此,原先的簡單查詢就有點心有余而力不足了
所以說,接下來就是進階的查詢!首先要確定一點的就是,查詢是針對記錄的,這點要明確哦
單表查詢
既然是進階,就一定有不一樣的花板子~完整的單表查詢指令如下:
select distinct字段名1,字段名2 from 庫.表
where 條件
group by 分組
having 過濾
order by 排序
limit 限制
;
簡單查詢
distinct:去重
mysql> select post from employee;
+-----------------------------------------+
| post |
+-----------------------------------------+
| 駐沙河辦事處外交大使 |
| teacher |
| teacher |
| teacher |
| teacher |
| teacher |
| teacher |
| teacher |
| sale |
| sale |
| sale |
| sale |
| sale |
| operation |
| operation |
| operation |
| operation |
| operation |
+-----------------------------------------+
18 rows in set (0.00 sec)
mysql> select distinct post from employee;
+-----------------------------------------+
| post |
+-----------------------------------------+
| 駐沙河辦事處外交大使 |
| teacher |
| sale |
| operation |
+-----------------------------------------+
4 rows in set (0.32 sec)
同時查詢的時候是支持四則運算的:
mysql> select name,salary*12 from employee;
+------------+-------------+
| name | salary*12 |
+------------+-------------+
| egon | 87603.96 |
| alex | 12000003.72 |
| wupeiqi | 99600.00 |
| yuanhao | 42000.00 |
| liwenzhou | 25200.00 |
| jingliyang | 108000.00 |
| jinxin | 360000.00 |
| 成龍 | 120000.00 |
| 歪歪 | 36001.56 |
| 丫丫 | 24004.20 |
| 丁丁 | 12004.44 |
| 星星 | 36003.48 |
| 格格 | 48003.96 |
| 張野 | 120001.56 |
| 程咬金 | 240000.00 |
| 程咬銀 | 228000.00 |
| 程咬銅 | 216000.00 |
| 程咬鐵 | 204000.00 |
+------------+-------------+
18 rows in set (0.00 sec)
mysql> select name,salary*12 as annual_salary from employee;
+------------+---------------+
| name | annual_salary |
+------------+---------------+
| egon | 87603.96 |
| alex | 12000003.72 |
| wupeiqi | 99600.00 |
| yuanhao | 42000.00 |
| liwenzhou | 25200.00 |
| jingliyang | 108000.00 |
| jinxin | 360000.00 |
| 成龍 | 120000.00 |
| 歪歪 | 36001.56 |
| 丫丫 | 24004.20 |
| 丁丁 | 12004.44 |
| 星星 | 36003.48 |
| 格格 | 48003.96 |
| 張野 | 120001.56 |
| 程咬金 | 240000.00 |
| 程咬銀 | 228000.00 |
| 程咬銅 | 216000.00 |
| 程咬鐵 | 204000.00 |
+------------+---------------+
18 rows in set (0.37 sec)
看到為什么寫兩個了吧,看到區別了吧~
還有就是字符串拼接,怎么拼接呢?
select concat('name:',name) from employee;
mysql> select concat('name:',name) from employee;
+------------------------+
| concat('name:',name) |
+------------------------+
| name:egon |
| name:alex |
| name:wupeiqi |
| name:yuanhao |
| name:liwenzhou |
| name:jingliyang |
| name:jinxin |
| name:成龍 |
| name:歪歪 |
| name:丫丫 |
| name:丁丁 |
| name:星星 |
| name:格格 |
| name:張野 |
| name:程咬金 |
| name:程咬銀 |
| name:程咬銅 |
| name:程咬鐵 |
+------------------------+
18 rows in set (0.00 sec)
where約束
where字句中可以使用:
- 比較運算符:> < >= <= <> !=
- between 80 and 100 值在80到100之間
- in(80,90,100) 值是10或20或30
- like 'ponny%'
pattern可以是%或_,
%表示任意多字符
_表示一個字符 - 邏輯運算符:在多個條件直接可以使用邏輯運算符 and or not
這個一部分講的在前面都有涉及,所以,就不舉例了,你自己嘗試使用
group by
這是分組,分組就是把有相同或相似特征的放在一起
比如說把男的都放在一起,把女的都放在一起
而且group by 只能夠查詢該分組的組名,查不到別的東西
mysql> select * from employee group by post;
+----+--------+--------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
| id | name | sex | age | hire_date | post | post_comment | salary | office | depart_id |
+----+--------+--------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
| 14 | 張野 | male | 28 | 2016-03-11 | operation | NULL | 10000.13 | 403 | 3 |
| 9 | 歪歪 | female | 48 | 2015-03-11 | sale | NULL | 3000.13 | 402 | 2 |
| 2 | alex | male | 78 | 2015-03-02 | teacher | NULL | 1000000.31 | 401 | 1 |
| 1 | egon | male | 18 | 2017-03-01 | 駐沙河辦事處外交大使 | NULL | 7300.33 | 401 | 1 |
+----+--------+--------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
4 rows in set (0.41 sec)
你這不騙我嗎?哪只有分組數據啊,這么多數據呢!
但是你會發現打印出來的都是每組的第一條數據,這是沒有意義的
別慌,其實這是mysql的設定,我們需要把模式改成嚴格模式才可以
set global sql_mode='ONLY_FULL_GROUP_BY';
怎么設置完還這樣呢?還記得設置自增時候的步長和起始偏移量的時候嗎?我們需要關掉重開一下!
mysql> select * from employee group by post;
ERROR 1055 (42000): 't.employee.id' isn't in GROUP BY
但是其實也沒有用,因為分組的目的不是想看看同類的,而是想對這些人做一個數據處理
比如像想統計人數啊之類的~~那就用到了聚合函數了!
那題道具和函數,就得好好說或聚合函數,聚合函數一共有這些:
max min avg sum count
比如說我們統計一下每個職位的人數~
select count(id) from employee group by post
mysql> select post,count(name) from employee group by post;
+-----------------------------------------+-------------+
| post | count(name) |
+-----------------------------------------+-------------+
| operation | 5 |
| sale | 5 |
| teacher | 7 |
| 駐沙河辦事處外交大使 | 1 |
+-----------------------------------------+-------------+
4 rows in set (0.00 sec)
要是想打印人數大於五的部門信息那我應該是這么寫:
select concat('職位:',post,' 人數:',count(name),
' 姓名:',group_concat(name)) as info,
count(name)>5 from employee group by post;
尤其是看到group_concat(name)的用法!!!
你可能執行的結果是這個:
+--------------------------------------------------------------------------------------------+--------+
| info | 數量 |
+--------------------------------------------------------------------------------------------+--------+
| 職位:operation人數:5姓名:程咬鐵,程咬銅,程咬銀,程咬金,張野 | 0 |
| 職位:sale人數:5姓名:格格,星星,丁丁,丫丫,歪歪 | 0 |
| 職位:teacher人數:7姓名:成龍,jinxin,jingliyang,liwenzhou,yuanhao,wupeiqi,alex | 1 |
| 職位:駐沙河辦事處外交大使人數:1姓名:egon | 0 |
+--------------------------------------------------------------------------------------------+--------+
這跟本來想的不一樣啊!別急~~~你還差一個知識點!先放在這
那我們可以逆向思維,如果不分組,是不是,就所有數據都是一組了!
那是不是也可以用聚合函數!
那我比如說想查找最高工資,是不是就會了!
having
這就是差的知識點!having 過濾
誒???我好像記得之前也有個過濾,好像是where,那他們有什么區別嗎?
#!!!執行優先級從高到低:where > group by > having
#1. Where 發生在分組group by之前,因而Where中可以有任意字段,但是絕對不能使用聚合函數。
#2. Having發生在分組group by之后,因而Having中可以使用分組的字段,無法直接取到其他字段,可以使用聚合函數
(驗證自己驗證ok?)
那餓哦們就可以接着把上面的代碼優化為:
select concat('職位:',post,'人數:',count(name),'姓名:',group_concat(name)) info from employee group by post having count(id)>5;
這回再打印,是不是就是預料之中的結果了!
order by
排序
表格默認的是id排序,那我想根據年齡排序,怎么辦呢?
select * from employee order by age;
可以看到是默認升序,那要是想要倒序呢?
select * from employee order by age desc
那你可能發現age有相等的時候,那我要是想相等的時候按照id排序怎么做呢?
select * from employee order by age,id
limit 限制
這個就是限制顯示條數,限制顯示前三條:
mysql> select * from employee limit 3;
+----+---------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
| id | name | sex | age | hire_date | post | post_comment | salary | office | depart_id |
+----+---------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
| 1 | egon | male | 18 | 2017-03-01 | 沙河辦事處外交大使 | NULL | 7300.33 | 401 | 1 |
| 2 | alex | male | 78 | 2015-03-02 | teacher | NULL | 1000000.31 | 401 | 1 |
| 3 | wupeiqi | male | 81 | 2013-03-05 | teacher | NULL | 8300.00 | 401 | 1 |
+----+---------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
3 rows in set (0.09 sec)
當然它其實還有分頁的功能:
select * from employee limit 0,5;
代表着從0開始往后取5個
(表結構看不清就看id)
select * from employee limit 0,5;
+----+-----------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
| id | name | sex | age | hire_date | post | post_comment | salary | office | depart_id |
+----+-----------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
| 1 | egon | male | 18 | 2017-03-01 | 駐沙河辦事處外交大使 | NULL | 7300.33 | 401 | 1 |
| 2 | alex | male | 78 | 2015-03-02 | teacher | NULL | 1000000.31 | 401 | 1 |
| 3 | wupeiqi | male | 81 | 2013-03-05 | teacher | NULL | 8300.00 | 401 | 1 |
| 4 | yuanhao | male | 73 | 2014-07-01 | teacher | NULL | 3500.00 | 401 | 1 |
| 5 | liwenzhou | male | 28 | 2012-11-01 | teacher | NULL | 2100.00 | 401 | 1 |
+----+-----------+------+-----+------------+-----------------------------------------+--------------+------------+--------+-----------+
5 rows in set (0.00 sec)
從5開始往后取五個:
mysql> select * from employee limit 5,5;
+----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+
| id | name | sex | age | hire_date | post | post_comment | salary | office | depart_id |
+----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+
| 6 | jingliyang | female | 18 | 2011-02-11 | teacher | NULL | 9000.00 | 401 | 1 |
| 7 | jinxin | male | 18 | 1900-03-01 | teacher | NULL | 30000.00 | 401 | 1 |
| 8 | 成龍 | male | 48 | 2010-11-11 | teacher | NULL | 10000.00 | 401 | 1 |
| 9 | 歪歪 | female | 48 | 2015-03-11 | sale | NULL | 3000.13 | 402 | 2 |
| 10 | 丫丫 | female | 38 | 2010-11-01 | sale | NULL | 2000.35 | 402 | 2 |
+----+------------+--------+-----+------------+---------+--------------+----------+--------+-----------+
5 rows in set (0.00 sec)
接下來的分頁就不演示了~
那在這我就要提一下書寫順序和執行順序了,畢竟約束條件這么多,總要有個優先級嘛:
正則表達式
where 后面雖然不能使用聚合函數,但是是可以使用正則匹配的
selece * from employee where name regexp '^ale';
以ale開頭的
其實他跟select * from employee where name like 'ale%';
是一樣的
select * from employee where name regexp 'on$';
以on結尾的
select * from employee where name regexp 'm{2}';
里面有mm的
以上的方法都自己去試一下
那我要是想以什么開頭,以什么結尾呢?
select * from employee where name regexp '^jin.*(g|n)$';
這就是以 jin 開頭,以g或者n結尾的name字段的數據
那至此,所有的約束就全結束了!
接下來就是多表查詢了~