mysql 進階查詢(學習筆記)

學習筆記,來源:實驗樓 ,連接: https://www.shiyanlou.com/courses/9mysql

 

 

 
1、日期計算:
一、要想肯定每一個寵物有多大,可使用函數TIMESTAMPDIFF()計算當前日期的年和出生日期之間的差也能夠按照直接使用語句 (YEAR(CURDATE())-YEAR(birth))計算,其中函數 CURDATE()是計算當前的日期。若是當前日期的日曆年比出生日期早,則減去一年。如下代碼是查詢每一個寵物的出生日期、當前日期和年齡(以年做爲計算單位),其中關鍵字age是年齡這個計算結果的標籤。
SELECT name, birth, CURDATE(),TIMESTAMPDIFF(YEAR,birth,CURDATE()) AS age FROM pet; SELECT name, birth, CURDATE(), (YEAR(CURDATE())-YEAR(birth)) - (RIGHT(CURDATE(),5)<RIGHT(birth,5)) AS age FROM pet ORDER BY name; 
YEAR()提取日期的年部分, RIGHT()提取日期最右面5個字符的MM-DD (月份和日期)部分。
 
二、查詢來肯定已經死亡動物的死亡年齡。你經過檢查death值是否爲NULL來肯定是哪些動物已經死亡,而後對於那些非NULL值的動物,須要計算出death和birth值之間的差來知道他們在這個世界上所存在的時間:
SELECT name, birth, death, (YEAR(death)-YEAR(birth)) - (RIGHT(death,5)<RIGHT(birth,5)) AS age FROM pet WHERE death IS NOT NULL ORDER BY age; 
查詢使用 death IS NOT NULL而非death != NULL,由於NULL是特殊的值,不能使用普通比較符來比較。
 
三、哪一個動物下個月過生日怎麼辦?對於這類計算,年和天是無關的,你只須要提取birth列的月份部分。MySQL提供幾個日期方面的提取函數,例如 YEAR()、MONTH()DAYOFMONTH()。在這裏MONTH()是咱們須要的函數。爲了觀察它的實現原理,能夠運行如下簡單的查詢顯示birth和MONTH(birth)的值:
SELECT name, birth FROM pet WHERE MONTH(birth) = MONTH(DATE_ADD(CURDATE(),INTERVAL 1 MONTH));、
DATE_ADD()容許在一個給定的日期上加上時間間隔。若是在NOW()值上加上一個月,而後用MONTH()提取月份,產生生日所在月份
 
四、完成該任務的另外一個方法是加1得出當前月份的下一個月(在使用取模函數 MOD()後,若是月份當前值是12,則「返回」到值0):
SELECT name, birth FROM pet WHERE MONTH(birth) = MOD(MONTH(CURDATE()), 12) + 1;
注意,MONTH返回在1和12之間的一個數字,且MOD(something,12)返回在0和11之間的一個數字,所以必須在MOD()後加1,不然咱們將從11月(11)跳到1月(1)。
 
2、模式匹配:
一、MySQL提供標準的SQL模式匹配,以及一種基於類Unix裏的程序如vi、grep和sed裏的擴展正則表達式模式匹配的格式。 SQL模式匹配容許你使用 「_」匹配任何單個字符,而 「%」匹配任意數目字符(包括零字符)。在 MySQL中,SQL的模式默認是忽略大小寫的。下面給出一些例子。注意使用SQL模式時,不能使用=或!=;而應使用LIKE或NOT LIKE比較操做符。
 
要想找出以「b」開頭的名字的動物信息:
mysql> SELECT * FROM pet WHERE name LIKE 'b%';
要想找出以「fy」結尾的名字:
mysql> SELECT * FROM pet WHERE name LIKE '%fy'; 
要想找出包含「w」的名字:
mysql> SELECT * FROM pet WHERE name LIKE '%w%';  
要想找出正好包含5個字符的名字,使用「_」模式字符:
mysql> SELECT * FROM pet WHERE name LIKE '_____';

  

二、由MySQL提供的模式匹配的其它類型是使用擴展正則表達式。當你對這類模式進行匹配測試時,使用 REGEXPNOT REGEXP操做符(或 RLIKENOT RLIKE,它們是同義詞)。 
 
擴展正則表達式的一些字符是:
  • ‘.’匹配任何單個的字符。
  • 字符類「[...]」匹配在方括號內的任何字符。例如,「[abc]」匹配「a」、「b」或「c」。爲了命名字符的範圍,使用一個「-」。「[a-z]」匹配任何字母,而「[0-9]」匹配任何數字。
  • 「 」匹配零個或多個在它前面的字符。例如,「x」匹配任何數量的「x」字符,「[0-9]」匹配任何數量的數字,而「.」匹配任何數量的任何字符。
 
若是 REGEXP模式與被測試值的任何地方匹配,模式就匹配(這不一樣於LIKE模式匹配,只有與整個值匹配,模式才匹配)。 爲了定位一個模式以便它必須匹配被測試值的開始或結尾,在模式開始處使用「^」或在模式的結尾用「$」。 爲了說明擴展正則表達式如何工做,下面使用REGEXP重寫上面所示的LIKE查詢:
 
爲了找出以「b」開頭的名字,使用「^」匹配名字的開始:
mysql> SELECT * FROM pet WHERE name REGEXP '^b'; 
若是你想強制使REGEXP比較區分大小寫,使用BINARY關鍵字使其中一個字符串變爲二進制字符串。該查詢只匹配名稱首字母的小寫‘b’。
mysql> SELECT * FROM pet WHERE name REGEXP BINARY '^b'; 
爲了找出以「fy」結尾的名字,使用「$」匹配名字的結尾:
mysql> SELECT * FROM pet WHERE name REGEXP 'fy$';  
爲了找出包含一個「w」的名字,使用如下查詢:
mysql> SELECT * FROM pet WHERE name REGEXP 'w';

 

三、既然若是一個正則表達式出如今值的任何地方,他就會被模式匹配,就沒必要在先前的查詢中在模式的兩側放置一個通配符以使得它匹配整個值,就像你使用了一個SQL模式那樣。
 
爲了找出包含正好5個字符的名字,使用「^」和「$」匹配名字的開始和結尾,和5個「.」實例在二者之間:
mysql> SELECT * FROM pet WHERE name REGEXP '^.....$'; 
你也可使用「{n}」重複n次操做符,重寫前面的查詢:
mysql> SELECT * FROM pet WHERE name REGEXP '^.{5}$';

  

3、計算行數:

計算你擁有動物的總數目與「在pet表中有多少行?」是一樣的問題,由於每一個寵物都對應一條記錄。COUNT(*)函數計算行數,因此計算動物數目的查詢應爲:
mysql> SELECT COUNT(*) FROM pet;
若是你想要知道每一個主人有多少寵物,你也可使用COUNT(*)函數:
mysql> SELECT owner, COUNT(*) FROM pet GROUP BY owner;
注意,使用GROUP BY對每一個owner的全部記錄分組,沒有它,你會獲得錯誤消息:
mysql> SELECT owner, COUNT(*) FROM pet;
ERROR 1140 (42000): Mixing of GROUP columns (MIN(),MAX(),COUNT(),...)
with no GROUP columns is illegal if there is no GROUP BY clause
COUNT(*)和GROUP BY以各類形式分類你的數據。下列例子顯示出以不一樣方式進行動物普查操做。
 
查看每種動物的數量:
mysql> SELECT species, COUNT(*) FROM pet GROUP BY species;
查看每種性別的動物數量:
mysql> SELECT sex, COUNT(*) FROM pet GROUP BY sex;
按種類和性別組合分類的動物數量:
mysql> SELECT species, sex, COUNT(*) FROM pet GROUP BY species, sex;
若使用COUNT(*),你沒必要檢索整個表。例如, 當只對狗和貓進行查詢時,應爲:
mysql> SELECT species, sex, COUNT(*) FROM pet WHERE species = 'dog' OR species = 'cat' GROUP BY species, sex;

或,若是你僅須要知道已知性別的按性別分組的動物數目: 正則表達式

mysql> SELECT species, sex, COUNT(*) FROM pet WHERE sex IS NOT NULL GROUP BY species, sex;

  

4、使用1個以上的表
 
pet表追蹤你擁有的寵物。若是你想要記錄其它相關信息,例如在他們看獸醫的狀況或後代出生的狀況,那麼你須要另外的表。這張表應該擁有些什麼呢?它須要:
 
須要包含寵物名字以便你知道每一個發生的事件屬於哪一個動物。
須要一個日期以便你知道事件是何時發生的。
須要一個描述事件的字段。
若是你想要對事件進行分類,則須要一個事件類型字段。
綜上所述, event表的CREATE TABLE語句應爲:
 
mysql> CREATE TABLE event (name VARCHAR(20), date DATE, type VARCHAR(15), remark VARCHAR(255));
 
相似於於pet表,最簡單的方法是建立一個用定位符分隔的文本文件來加載載初始記錄:
 
 
採用以下方式加載記錄:
mysql> LOAD DATA LOCAL INFILE '/home/shiyanlou/Desktop/event.txt' INTO TABLE event; 
 
 
因爲你已經在 pet表上的查詢中學到了必定的知識,你應該能執行對 event表中記錄的檢索;原理是同樣的。可是有沒有event表自己不能回答你可能問的問題呢?
 
當寵物們生了了一窩小動物時,假定你想要找出這時候每隻寵物的年齡。咱們前面看到了如何經過兩個日期計算年齡。event表中有母親的生產日期,可是爲了計算母親的年齡,你須要她的出生日期,存儲在pet表中。說明查詢須要兩個表:
mysql> SELECT pet.name,
-> (YEAR(date)-YEAR(birth)) - (RIGHT(date,5)<RIGHT(birth,5)) AS age,
-> remark
-> FROM pet, event
-> WHERE pet.name = event.name AND event.type = 'litter';
 
 
關於該查詢要注意如下幾件事:
 
FROM子句鏈接兩個表,由於查詢須要從兩個表中提取信息。
當從多個表組合(聯結)信息時,你須要指定其中一個表中的列明以期匹配其它表的列名。這很簡單,由於它們都有一個name列,查詢能夠經過使用WHERE子句基於name值來匹配兩個表中的記錄。
 
由於name列都存在兩個表中,所以 當引用該列時,必定要指定是哪一個表,把表名附在列名前便可以實現。 若是你想要將一個表的記錄與該表的其它記錄進行比較,能夠將該表聯結到自身。例如,爲了在你的寵物之中選擇繁殖中的配偶,你能夠用pet表聯結自身來進行相同種類的雄雌配對:
mysql> SELECT p1.name, p1.sex, p2.name, p2.sex, p1.species
-> FROM pet AS p1, pet AS p2
-> WHERE p1.species = p2.species AND p1.sex = 'f' AND p2.sex = 'm';  
在這個查詢中,咱們爲表名指定別名p1和p2以便能引用它們的列而且使得每個列的引用更直觀。
 
 
5、得到數據庫和表的信息
 
一、若是你忘記數據庫或表的名字,或給定的表的結構是什麼(例如,它的列叫什麼),怎麼辦?MySQL提供一些語句解決這個問題。 你已經知道SHOW DATABASES能夠列出由服務器管理的全部數據庫。爲了找出當前選擇了哪一個數據庫,使用 DATABASE()函數:
 mysql> SELECT DATABASE(); 
若是你還沒選擇任何數據庫,結果是 NULL
二、爲了找出當前的數據庫包含什麼表(例如,當你不能肯定一個表的名字),使用這個命令:
mysql> SHOW TABLES; 
三、若是你想要知道一個表的結構,可使用 DESCRIBE命令;它顯示錶中每一個列的信息:
mysql> DESCRIBE pet;
Field顯示列名字, Type是列的數據類型, Null表示列是否能包含NULL值, key顯示列是否被索引而 Default指定列的默認值。
若是表有索引,SHOW INDEX FROM tbl_name生成有關索引的信息。
 
相關文章
相關標籤/搜索