MySQL管理之SQL語句實例mysql
首先,咱們來導入world庫,這個world庫中的表是mysql ocp考試專用表,在網上有下sql
mysql> source/root/world_innodb.sqlapi
表結構以下: 本文來自http://yijiu.blog.51cto.com 轉載請經博主容許 ,盜帖可恥!併發
CREATE TABLE `Country` (
`Code` char(3) NOT NULL DEFAULT '',
`Name` char(52) NOT NULL DEFAULT '',
`Continent` enum('Asia','Europe','North America','Africa','Oceania','Antarctica','South America') NOT NULL DEFAULT 'Asia',
`Region` char(26) NOT NULL DEFAULT '',
`SurfaceArea` float(10,2) NOT NULL DEFAULT '0.00',
`IndepYear` smallint(6) DEFAULT NULL,
`Population` int(11) NOT NULL DEFAULT '0',
`LifeExpectancy` float(3,1) DEFAULT NULL,
`GNP` float(10,2) DEFAULT NULL,
`GNPOld` float(10,2) DEFAULT NULL,
`LocalName` char(45) NOT NULL DEFAULT '',
`GovernmentForm` char(45) NOT NULL DEFAULT '',
`HeadOfState` char(60) DEFAULT NULL,
`Capital` int(11) DEFAULT NULL,
`Code2` char(2) NOT NULL DEFAULT '',
PRIMARY KEY (`Code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8ide
使用show table status查看錶狀態以下所示:函數
mysql> show tablestatus;測試
+-----------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-------------------+----------+----------------+---------+優化
| Name | Engine | Version | Row_format |Rows | Avg_row_length | Data_length | Max_data_length | Index_length |Data_free | Auto_increment | Create_time | Update_time | Check_time | Collation | Checksum | Create_options | Comment|ui
+-----------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-------------------+----------+----------------+---------+spa
| City | InnoDB | 10 | Compact | 4321 | 94 | 409600 | 0 | 131072 | 0 | 4080 | 2014-10-02 15:35:18 |NULL | NULL | latin1_swedish_ci | NULL | | |
| Country | InnoDB | 10 | Compact | 241 | 407 | 98304 | 0 | 0 | 0 | NULL | 2014-10-02 15:35:18 |NULL | NULL | latin1_swedish_ci | NULL | | |
| CountryLanguage |InnoDB | 10 | Compact | 856 | 114 | 98304 | 0 | 65536 | 0 | NULL | 2014-10-02 15:35:18 |NULL | NULL | latin1_swedish_ci | NULL | | |
+-----------------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-------------------+----------+----------------+---------+
3 rows in set (0.00sec)
mysql> select *from Country where Name="China"\G
***************************1. row ***************************
Code: CHN
Name: China
Continent: Asia
Region: Eastern Asia
SurfaceArea: 9572900.00
IndepYear: -1523
Population: 1277558000
LifeExpectancy: 71.4
GNP: 982268.00
GNPOld: 917719.00
LocalName: Zhongquo
GovernmentForm:People'sRepublic
HeadOfState: Jiang Zemin
Capital: 1891
Code2: CN
1 row in set (0.00sec)
本文來自http://yijiu.blog.51cto.com 轉載請經博主容許 ,盜帖可恥!
由此能夠看到此表與City表關聯,以下所示
由於city表存在城市ID編號,也就是剛纔與Capital= 1891 相關的信息
mysql> select *from City where id = 1891;
+------+--------+-------------+----------+------------+
| ID | Name | CountryCode | District | Population |
+------+--------+-------------+----------+------------+
| 1891 | Peking | CHN | Peking | 7472000 |
+------+--------+-------------+----------+------------+
1 row in set (0.00sec)
而CountryLanguage表裏是將CountryCode作關聯
看到編號爲CHN,那查一下關於CHN相關的信息
可看到CountryLanguage用到以CHN做爲關聯能夠查到相關城市
mysql> select *from CountryLanguage where CountryCode = 'CHN';
+-------------+-----------+------------+------------+
| CountryCode |Language | IsOfficial | Percentage |
+-------------+-----------+------------+------------+
| CHN | Chinese | T | 92.0 |
| CHN | Dong | F | 0.2 |
| CHN | Hui | F | 0.8 |
| CHN | Mantu | F | 0.9 |
| CHN | Miao |F | 0.7 |
| CHN | Mongolian | F | 0.4 |
| CHN | Puyi | F | 0.2 |
| CHN | Tibetan | F | 0.4 |
| CHN | Tujia | F | 0.5 |
| CHN | Uighur | F | 0.6 |
| CHN | Yi | F | 0.6 |
| CHN | Zhuang | F | 1.4 |
+-------------+-----------+------------+------------+
12 rows in set (0.00sec)
接下來就進入主題
查詢語句初識 本文來自http://yijiu.blog.51cto.com 轉載請經博主容許 ,盜帖可恥!
來個例子先,查找City表中的前10行
mysql> select Id,Name, Population From City limit 10;
+----+----------------+------------+
| Id | Name | Population |
+----+----------------+------------+
| 1 | Kabul | 1780000 |
| 2 | Qandahar | 237500 |
| 3 | Herat | 186800 |
| 4 | Mazar-e-Sharif | 127800 |
| 5 | Amsterdam | 731200 |
| 6 | Rotterdam | 593321 |
| 7 | Haag | 440900 |
| 8 | Utrecht | 234323 |
| 9 | Eindhoven | 201843 |
| 10 | Tilburg | 193238 |
+----+----------------+------------+
10 rows in set (0.00sec)
查找從第10行到20行,中間相差10行
limit 10,10;意思爲從第幾行開始並從這行開始向下顯示多少行
mysql> select Id,Name, Population From City limit 10,10;
+----+-------------------+------------+
| Id | Name | Population |
+----+-------------------+------------+
| 11 | Groningen | 172701 |
| 12 | Breda | 160398 |
| 13 | Apeldoorn | 153491 |
| 14 | Nijmegen | 152463 |
| 15 | Enschede | 149544 |
| 16 | Haarlem | 148772 |
| 17 | Almere | 142465 |
| 18 | Arnhem | 138020 |
| 19 | Zaanstad | 135621 |
| 20 |s-Hertogenbosch | 129170 |
+----+-------------------+------------+
10 rows in set (0.00sec)
錯誤的sql:以下所示
select * from tb where xxxx limit 537793977, 20;
若是出現這樣的sql,意味着先要掃描表裏面的537793977行後再取20行返回,這樣成本就會很高
LIMIT的一個原則:
在生產環境中使用LIMIT後只跟一個數,並且最好不大於500,若是是連續的,包括上面的sql,利用上面的SQL獲得一個ID的最大值,那麼這時候咱們就會用到份頁
以下所示:
優化前:
mysql> select Id,Name, Population From City limit 10;
+----+----------------+------------+
| Id | Name | Population |
+----+----------------+------------+
| 1 | Kabul | 1780000 |
| 2 | Qandahar | 237500 |
| 3 | Herat | 186800 |
| 4 | Mazar-e-Sharif | 127800 |
| 5 | Amsterdam | 731200 |
| 6 | Rotterdam | 593321 |
| 7 | Haag | 440900 |
| 8 | Utrecht | 234323 |
| 9 | Eindhoven | 201843 |
| 10 | Tilburg | 193238 |
+----+----------------+------------+
10 rows in set (0.00sec)
優化後以下:
使用last_max_id經過程序進行計算獲得的
語法:
mysql>select Id, Name, Population From City where id ><last_max_id> limit 10;
mysql> select Id,Name, Population From City where id >10 limit 10;
+----+-------------------+------------+
| Id | Name | Population |
+----+-------------------+------------+
| 11 | Groningen | 172701 |
| 12 | Breda | 160398 |
| 13 | Apeldoorn | 153491 |
| 14 | Nijmegen | 152463 |
| 15 | Enschede | 149544 |
| 16 | Haarlem | 148772 |
| 17 | Almere | 142465 |
| 18 | Arnhem | 138020 |
| 19 | Zaanstad | 135621 |
| 20 |s-Hertogenbosch | 129170 |
+----+-------------------+------------+
10 rows in set (0.00sec)
本文來自http://yijiu.blog.51cto.com 轉載請經博主容許 ,盜帖可恥!
參數解釋:
where id> 10 limit 10 就是取前10行到第20行
若是取前10的話,將數據放進去,獲得的就是last_max_id而後傳到下一頁,進行對比
這就是所謂的分頁
#這並非徹底在sql裏實現的, 若是想特別精準的分頁,這種訪問有可能有問題的。
#跳頁的話有種方法:通常粗略的估計一下便可,不會讓其很是精準的顯示出來,只求速度足夠快
好比跳頁,若是對於整個系統進行搜索的話,非查不可的狀況,咱們可使用專屬的搜索系統進行查看,互聯網領域中能不進行寫則不寫,以提升速度
count, max(), min()使用
count
count(*)在早版本會走主鍵的,最新版本會走普通索引
mysql> selectcount(*), count(id) from City;
+----------+-----------+
| count(*) | count(id)|
+----------+-----------+
| 4079 | 4079 |
+----------+-----------+
1 row in set (0.00sec)
那麼問題來了:主建爲什麼沒有第二索引快?
由於Innodb主建就表自己裏的數據,若是count主建,須要將整個表掃描一遍,這樣建帶數據讀的塊更大
走主建至關於把整個表都要讀(全表掃描) 本文來自http://yijiu.blog.51cto.com 轉載請經博主容許 ,盜帖可恥!
而在Innodb裏是索引列+主建值存儲的結構體系,這麼作的話會更快
若是直接使用Secondary index的話會快一點
現在mysql對count(*)作了優化,默認會走Secondary index,因此在之後計算總數的時候,不要總計算列數,直接寫count(*)就能夠了
列出人數最多的城市
咱們如今有需求,咱們知道City表中有城市的總人數,咱們如今想統計一下最多人數的城市
那麼咱們先來看一下表結構 本文來自http://yijiu.blog.51cto.com 轉載請經博主容許 ,盜帖可恥!
mysql> desc City ;
+-------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+----------+------+-----+---------+----------------+
| ID | int(11) | NO | PRI | NULL | auto_increment |
| Name | char(35) | NO | | | |
| CountryCode |char(3) | NO | MUL | | |
| District | char(20) | NO | | | |
| Population | int(11) | NO | | 0 | |
+-------------+----------+------+-----+---------+----------------+
5 rows in set (0.00sec)
由此咱們可知條件,Population爲每一個城市的總人數,咱們只要篩出Population最大的值便可,以下所示:
mysql> select * from City where Population = (selectmax(Population) from City);
+------+-----------------+-------------+-------------+------------+
| ID | Name | CountryCode | District | Population |
+------+-----------------+-------------+-------------+------------+
| 1024 | Mumbai(Bombay) | IND | Maharashtra| 10500000 |
+------+-----------------+-------------+-------------+------------+
1 row in set (0.00sec)
括號中內的內容爲子句查詢;
而select max(Population) from City 表示查找這個表中人數最多的行
先來看一個例子,執行上面的sql子句:
mysql> selectmax(Population) from City;
+-----------------+
| max(Population) |
+-----------------+
| 10500000 |
+-----------------+
1 row in set (0.00sec)
max是內置函數,表示將取最大數值的行
那麼將其封裝到子句裏面,再進行對比,即 Population= 最大的字段
找到城市人數最少的城市
mysql> select *from City where Population = (select min(Population) from City);
+------+-----------+-------------+----------+------------+
| ID | Name | CountryCode | District | Population |
+------+-----------+-------------+----------+------------+
| 2912 | Adamstown |PCN | – | 42 |
+------+-----------+-------------+----------+------------+
1 row in set (0.01sec)
使用oder by進行排序
mysql> select *from City order by Population desc limit1;
+------+-----------------+-------------+-------------+------------+
| ID | Name | CountryCode | District | Population |
+------+-----------------+-------------+-------------+------------+
| 1024 | Mumbai(Bombay) | IND | Maharashtra| 10500000 |
+------+-----------------+-------------+-------------+------------+
1 row in set (0.00sec)
本文來自http://yijiu.blog.51cto.com 轉載請經博主容許 ,盜帖可恥!
查找大於人員數大於100W的城市有有哪些
使用count(*) 統計出總數
mysql> selectcount(*) from City where Population > 1000000;
+----------+
| count(*) |
+----------+
| 237 |
+----------+
1 row in set (0.00sec)
可看到 一共有237個城市
那麼再來查找人口大於100W的城市是否一共有237個
mysql> select *from City where Population >1000000;
#拉到最後可看到以下的數值
+------+--------------------------+-------------+----------------------+------------+
237 rows in set (0.00sec)
咱們還可使用函數,若是什麼參數都沒有加的狀況下就使用如下函數,會獲得上一個sql的執行所獲得的行數
mysql> selectfound_rows();
+--------------+
| found_rows() |
+--------------+
| 237 |
+--------------+
1 row in set (0.00sec)
本文來自http://yijiu.blog.51cto.com 轉載請經博主容許 ,盜帖可恥!
那麼使用count(*)並執行函數來查看效果又會是什麼樣
mysql> selectcount(*) from City where Population > 1000000;
+----------+
| count(*) |
+----------+
| 237 |
+----------+
1 row in set (0.00sec)
mysql> selectfound_rows();
+--------------+
| found_rows() |
+--------------+
| 1 |
+--------------+
1 row in set (0.00sec)
FOUND_ROWS函數
好比取前10行,但表中總共有多少行是未知的,這裏在比其餘數據中多了一個函數:
SQL_CALC_FOUND_ROWS
先來看一下yw表有多少行
mysql> selectcount(*) from yw;
+----------+
| count(*) |
+----------+
| 6000000 |
+----------+
1 row in set (15.64sec)
再執行打印前10行內容
mysql> select SQL_CALC_FOUND_ROWS * fromCity limit 10;
ERROR 1146 (42S02):Table 'test1.City' doesn't exist
mysql> select SQL_CALC_FOUND_ROWS* from yw limit 10;
+----+---------+---------+---------+---------+---------------------+------------------------------------------------------+
| id | c1 | c2 | c3 | c4 | c5 | c6 |
+----+---------+---------+---------+---------+---------------------+------------------------------------------------------+
| 1 | 463681 | 1098981 | 1817518 | 2222359 | 2014-09-24 15:38:29 |wubxwubxwubxwubxwubxwubxwubxwubxwubxwubxwubxwubx |
| 2 | 2333997 | 269341 | 2459005 | 915557 |2014-09-24 15:38:29 | wubxwubxwubx |
| 3 | 2971523 | 1226698 | 842469 | 414525 | 2014-09-24 15:38:29 | wubxwubxwubxwubxwubxwubxwubxwubxwubx |
| 4 | 2835700 | 930937 | 2835332 | 1945110 | 2014-09-24 15:38:29 | wubx |
| 5 | 1578655 | 1044887 | 2649255 | 2307696 |2014-09-24 15:38:29 | wubxwubxwubxwubxwubxwubxwubx |
| 6 | 1442242 | 992011 | 1740281 | 190626 |2014-09-24 15:38:29 | wubxwubxwubxwubxwubxwubxwubxwubxwubxwubxwubxwubxwubx |
| 7 | 693798 | 309586 | 753637 | 2403923 | 2014-09-24 15:38:29 |wubxwubxwubxwubxwubxwubxwubxwubxwubxwubx |
| 8 | 888272 | 2581335 | 1547343 | 1465295 | 2014-09-24 15:38:29 |wubxwubxwubxwubx |
| 9 | 1608599 | 240304 | 2475805 | 2157717 | 2014-09-24 15:38:29 | wubxwubxwubxwubx |
| 10 | 2833881 | 185188 | 1736996 | 565924 | 2014-09-24 15:38:29 |wubxwubxwubxwubxwubxwubxwubxwubxwubxwubx |
+----+---------+---------+---------+---------+---------------------+------------------------------------------------------+
10 rows in set (17.88sec)
mysql> selectfound_rows();
+--------------+
| found_rows() |
+--------------+
| 6000000 |
+--------------+
1 row in set (0.00sec)
6000000就是表的行數
若是併發比較大的狀況下,這個函數用的仍是比較多的,可是通常不會直接一個表就直接使用found_rows,通常都是跟where條件,跟上條件並計算此類型的條目數,通常此類場景中比較常見
主要就是用SQL_CALC_FOUND_ROWS來減小操做爲主要目的
模糊匹配
使用like
語法:like "Wu%" #不能以百分號開頭,若是使用%開頭,則不會用到索引
查詢以wu開頭的城市
mysql> select *from City where Name like 'Wu%';
+------+-----------+-------------+---------------------+------------+
| ID | Name | CountryCode | District | Population |
+------+-----------+-------------+---------------------+------------+
| 1894 | Wuhan | CHN | Hubei | 4344600 |
| 1929 | Wuxi | CHN | Jiangsu | 830000 |
| 1964 | Wuhu | CHN | Anhui | 425740 |
| 2022 | Wuhai | CHN | Inner Mongolia | 264081 |
| 2058 | Wuzhou | CHN | Guangxi | 210452 |
| 2163 | Wuwei | CHN | Gansu | 133101 |
| 3084 | Wuppertal |DEU | Nordrhein-Westfalen | 368993 |
+------+-----------+-------------+---------------------+------------+
7 rows in set (0.01sec)
不用過多作解釋了
使用sum統計其列總數
sum也是mysql內置函數,用法都是同樣的,以下所示:
咱們來統計中國幾個重要城市的人口總數
mysql> selectsum(Population) from City;
+-----------------+
| sum(Population) |
+-----------------+
| 1429559884 |
+-----------------+
1 row in set (0.00sec)
mysql> selectsum(Population) from City where CountryCode='CHN';
+-----------------+
| sum(Population) |
+-----------------+
| 175953614 |
+-----------------+
1 row in set (0.00sec)
或只統計上海和天津的總人數
mysql> selectsum(Population) from City where CountryCode='CHN' and Name='TianJin' orName='ShangHai';
+-----------------+
| sum(Population) |
+-----------------+
| 14983100 |
+-----------------+
1 row in set (0.00sec)
使用表關聯,查看出每一個國家的首都
剛纔咱們直接使用了sum查到了首都的詳細信息,若是使用表關聯使用這兩個表來查咱們首都詳細信息的話,該如何去查
由於咱們知道Code:CHN,那麼咱們使用Capital字段與city表的id進行關聯:
先來查看錶內容:
mysql> select * from Country limit 1;
+------+-------+---------------+-----------+-------------+-----------+------------+----------------+--------+--------+-----------+----------------------------------------------+-------------+---------+-------+
| Code | Name | Continent | Region | SurfaceArea | IndepYear | Population | LifeExpectancy | GNP | GNPOld | LocalName | GovernmentForm | HeadOfState | Capital | Code2|
+------+-------+---------------+-----------+-------------+-----------+------------+----------------+--------+--------+-----------+----------------------------------------------+-------------+---------+-------+
| ABW | Aruba | North America | Caribbean | 193.00 | NULL | 103000 | 78.4 | 828.00 |793.00 | Aruba | NonmetropolitanTerritory of The Netherlands | Beatrix | 129 |AW |
+------+-------+---------------+-----------+-------------+-----------+------------+----------------+--------+--------+-----------+----------------------------------------------+-------------+---------+-------+
1 row in set (0.00 sec)
如上能夠看到,Country表的Capital是指向國家首都城市的id,因此利用關聯能夠獲得
可使用Country表的Capital和City表id關聯,並加上限制Country.Code='CHN';
mysql> selecta.name,b.name from Country a , City b where a.Code="CHN" and a.Capital=b.id;
+-------+--------+
| name | name |
+-------+--------+
| China | Peking |
+-------+--------+
1 row in set (0.00sec)
語法解釋:
語法可分爲兩截:
select a.name,b.namefrom Country a , City b ; 這是一段
where a.Code="CHN" and a.Capital=b.id; 這又是一段
先來執行第一段
mysql> selecta.name,b.name from Country a , City b limit 1;
+-------+-------+
| name | name |
+-------+-------+
| Aruba | Kabul |
+-------+-------+
1 row in set (0.00sec)
能夠看到,每一個國家的名稱以及國家的首都都呈現出來
那麼咱們想針對某個國家查看其首都的話確定須要加where條件進行匹配了
where的同時,首先須要統計國家的代碼號,中國無非是CHN,可是隻是篩選出了CHN的城市,並無曬出其首都,以下所示
mysql> selecta.name,b.name from Country a ,City b where a.Code='CHN' limit 10;
+-------+----------------+
| name | name |
+-------+----------------+
| China | Kabul |
| China |Qandahar |
| China | Herat |
| China |Mazar-e-Sharif |
| China |Amsterdam |
| China |Rotterdam |
| China | Haag |
| China |Utrecht |
| China | Eindhoven |
| China |Tilburg |
+-------+----------------+
10 rows in set (0.00sec)
咱們還須要對其作條件匹配,咱們看到,Country表中有Capital的字段,沒錯這是國家首都編號,而City中也存在城市的ID,那麼這兩個字段是相等的,因此咱們只要將Counry表中的Capital和City表中的城市ID匹配上便可,以下所示:
mysql> selecta.name,b.name from Country a , City b where a.Code='CHN' and a.Capital=b.id;
+-------+--------+
| name | name |
+-------+--------+
| China | Peking |
+-------+--------+
1 row in set (0.00sec)
country爲爲別名a
city的別名爲b
並使用where進行別名a
也就是country表中的code進行匹配
若是某行等於CHN,而且與別名b表中,也就是city表中的id匹配,則打印
若是想看每一個國家的首都在哪裏,則以下:
mysql> selecta.name,b.name from Country a , City b where a.Capital=b.id limit 10;
+----------------------+------------------+
| name | name |
+----------------------+------------------+
| Aruba | Oranjestad |
| Afghanistan | Kabul |
| Angola | Luanda |
| Anguilla | The Valley |
| Albania | Tirana |
| Andorra | Andorra la Vella |
| NetherlandsAntilles | Willemstad |
| United ArabEmirates | Abu Dhabi |
| Argentina | Buenos Aires |
| Armenia | Yerevan |
+----------------------+------------------+
10 rows in set (0.00sec)
將其餘表中的數據導入到當前表
建立一個測試表及相關操做
mysql> createtable test5 like City;
Query OK, 0 rowsaffected (0.02 sec)
從其餘表往新表中導入記錄
mysql> insert intotest5 select * from City limit 100;
Query OK, 100 rowsaffected (0.00 sec)
Records: 100 Duplicates: 0 Warnings: 0
當在線上環境,想調整索引,可是原表確大,不容易操做時,能夠上面的方法建一個測試表,測試完後再刪掉就能夠了
使用update更新表數據
使用update將北京更名
mysql> updatetest5 set Name='Peking', District='Peking' where id=1;
Query OK, 1 rowaffected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0
若是須要更新多個列的話,必須以逗號間隔開來
UPDATE重大標識:
若是update沒有加條件等於全表更新,因此執行update的時候必定要加where條件
或者把事務開起來,或是把自動提交關了
begin;
update test5 set Name='Peking', District='aaa' where id=1;
select * from test5 where id=1; #確認一下
rollback; or commit; #沒有問題再提交操做
delete 操做:
刪除添加的第一條記錄,也要考慮事務操做:
begin;
delete from wubx_1 where id=1;
select * from wubx_1 where id=1;
rollback |commit
以上,爲MySQL的平常sql實例,感謝各位看官