MySQL入門教程5 —— 從數據表中檢索信息
SELECT語句用來從數據表中檢索信息。語句的一般格式是:
SELECT what_to_select FROM which_table WHERE conditions_to_satisfy;
what_to_select指出你想要看到的內容,可以是列的一個表,或*表示“所有的列”。which_table指出你想要從其檢索數據的表。WHERE子句是可選項,如果選擇該項,conditions_to_satisfy指定行必須滿足的檢索條件。
1. 選擇所有數據SELECT最簡單的形式是從一個表中檢索所有記錄:
mysql> SELECT * FROM pet; +----------+--------+---------+------+------------+------------+| name | owner | species | sex | birth | death |+----------+--------+---------+------+------------+------------+| Fluffy | Harold | cat | f | 1993-02-04 | NULL || Claws | Gwen | cat | m | 1994-03-17 | NULL || Buffy | Harold | dog | f | 1989-05-13 | NULL || Fang | Benny | dog | m | 1990-08-27 | NULL || Bowser | Diane | dog | m | 1979-08-31 | 1995-07-29 || Chirpy | Gwen | bird | f | 1998-09-11 | NULL || Whistler | Gwen | bird | NULL | 1997-12-09 | NULL || Slim | Benny | snake | m | 1996-04-29 | NULL || Puffball | Diane | hamster | f | 1999-03-30 | NULL |+----------+--------+---------+------+------------+------------+
如果你想要瀏覽整個表,可以使用這種形式的SELECT,例如,剛剛裝載了初始數據集以后。也有可能你想到Bowser的生日看起來不很對。查閱你原來的家譜,你發現正確的出生年是1989,而不是1979。
至少有兩種修正方法:
·編輯文件“pet.txt”改正錯誤,然后使用DELETE和LOAD DATA清空并重新裝載表:
mysql> DELETE FROM pet; mysql> LOAD DATA LOCAL INFILE ’pet.txt’ INTO TABLE pet;
然而, 如果這樣操做,必須重新輸入Puffball記錄。
·用一個UPDATE語句僅修正錯誤記錄:
mysql> UPDATE pet SET birth = ’1989-08-31’ WHERE name = ’Bowser’;
UPDATE只更改有問題的記錄,不需要重新裝載數據庫表。
2. 選擇特殊行如上所示,檢索整個表是容易的。只需要從SELECT語句中刪掉WHERE子句。但是一般你不想看到整個表,特別地當表變得很大時。相反,你通常對回答一個具體的問題更感興趣,在這種情況下在你想要的信息上進行一些限制。讓我們看一些他們回答的有關你寵物的問題的選擇查詢。可以從表中只選擇特定的行。例如,如果你想要驗證你對Bowser的生日所做的更改,按下述方法選擇Bowser的記錄:
mysql> SELECT * FROM pet WHERE name = ’Bowser’; +--------+-------+---------+------+------------+------------+| name | owner | species | sex | birth | death |+--------+-------+---------+------+------------+------------+| Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 |+--------+-------+---------+------+------------+------------+
輸出證實正確的年份記錄為1989,而不是1979。
字符串比較時通常對大小些不敏感,因此你可以將名字指定為'bowser'、'BOWSER'等,查詢結果相同。
你可以在任何列上指定條件,不只僅僅是name。例如,如果你想要知道哪個動物在1998以后出生的,測試birth列:
mysql> SELECT * FROM pet WHERE birth > ’1998-1-1’; +----------+-------+---------+------+------------+-------+| name | owner | species | sex | birth | death |+----------+-------+---------+------+------------+-------+| Chirpy | Gwen | bird | f | 1998-09-11 | NULL || Puffball | Diane | hamster | f | 1999-03-30 | NULL |+----------+-------+---------+------+------------+-------+
可以組合條件,例如,找出雌性的狗:
mysql> SELECT * FROM pet WHERE species = ’dog’ AND sex = ’f’;
+-------+--------+---------+------+------------+-------+| name | owner | species | sex | birth | death |+-------+--------+---------+------+------------+-------+| Buffy | Harold | dog | f | 1989-05-13 | NULL |+-------+--------+---------+------+------------+-------+
上面的查詢使用AND邏輯操作符,也有一個OR操作符:
mysql> SELECT * FROM pet WHERE species = ’snake’ OR species = ’bird’; +----------+-------+---------+------+------------+-------+| name | owner | species | sex | birth | death |+----------+-------+---------+------+------------+-------+| Chirpy | Gwen | bird | f | 1998-09-11 | NULL || Whistler | Gwen | bird | NULL | 1997-12-09 | NULL || Slim | Benny | snake | m | 1996-04-29 | NULL |+----------+-------+---------+------+------------+-------+
AND和OR可以混用,但AND比OR具有更高的優先級。如果你使用兩個操作符,使用圓括號指明如何對條件進行分組是一個好主意:
mysql> SELECT * FROM pet WHERE (species = ’cat’ AND sex = ’m’) -> OR (species = ’dog’ AND sex = ’f’); +-------+--------+---------+------+------------+-------+| name | owner | species | sex | birth | death |+-------+--------+---------+------+------------+-------+| Claws | Gwen | cat | m | 1994-03-17 | NULL || Buffy | Harold | dog | f | 1989-05-13 | NULL |+-------+--------+---------+------+------------+-------+3. 選擇特殊列
如果你不想看到表中的所有行,就命名你感興趣的列,用逗號分開。例如,如果你想要知道你的動物什么時候出生的,選擇name和birth列:
mysql> SELECT name, birth FROM pet; +----------+------------+| name | birth |+----------+------------+| Fluffy | 1993-02-04 || Claws | 1994-03-17 || Buffy | 1989-05-13 || Fang | 1990-08-27 || Bowser | 1989-08-31 || Chirpy | 1998-09-11 || Whistler | 1997-12-09 || Slim | 1996-04-29 || Puffball | 1999-03-30 |+----------+------------+
找出誰擁有寵物,使用這個查詢:
mysql> SELECT owner FROM pet; +--------+| owner |+--------+| Harold || Gwen || Harold || Benny || Diane || Gwen || Gwen || Benny || Diane |+--------+
請注意該查詢只是簡單地檢索每個記錄的owner列,并且他們中的一些出現多次。為了使輸出減到最少,增加關鍵字DISTINCT檢索出每個唯一的輸出記錄:
mysql> SELECT DISTINCT owner FROM pet; +--------+| owner |+--------+| Benny || Diane || Gwen || Harold |+--------+
可以使用一個WHERE子句結合行選擇與列選擇。例如,要想查詢狗和貓的出生日期,使用這個查詢:
mysql> SELECT name, species, birth FROM pet -> WHERE species = ’dog’ OR species = ’cat’; +--------+---------+------------+| name | species | birth |+--------+---------+------------+| Fluffy | cat | 1993-02-04 || Claws | cat | 1994-03-17 || Buffy | dog | 1989-05-13 || Fang | dog | 1990-08-27 || Bowser | dog | 1989-08-31 |+--------+---------+------------+4. 分類行
你可能已經注意到前面的例子中結果行沒有以特定的順序顯示。然而,當行按某種方式排序時,檢查查詢輸出通常更容易。為了排序結果,使用ORDER BY子句。這里是動物生日,按日期排序:
mysql> SELECT name, birth FROM pet ORDER BY birth; +----------+------------+| name | birth |+----------+------------+| Buffy | 1989-05-13 || Bowser | 1989-08-31 || Fang | 1990-08-27 || Fluffy | 1993-02-04 || Claws | 1994-03-17 || Slim | 1996-04-29 || Whistler | 1997-12-09 || Chirpy | 1998-09-11 || Puffball | 1999-03-30 |+----------+------------+
在字符類型列上,與所有其他比較操作類似,分類功能正常情況下是以區分大小寫的方式執行的。這意味著,對于等同但大小寫不同的列,并未定義其順序。對于某一列,可以使用BINARY強制執行區分大小寫的分類功能,如:ORDER BY BINARY col_name.
默認排序是升序,最小的值在第一。要想以降序排序,在你正在排序的列名上增加DESC(降序 )關鍵字:
mysql> SELECT name, birth FROM pet ORDER BY birth DESC; +----------+------------+| name | birth |+----------+------------+| Puffball | 1999-03-30 || Chirpy | 1998-09-11 || Whistler | 1997-12-09 || Slim | 1996-04-29 || Claws | 1994-03-17 || Fluffy | 1993-02-04 || Fang | 1990-08-27 || Bowser | 1989-08-31 || Buffy | 1989-05-13 |+----------+------------+
可以對多個列進行排序,并且可以按不同的方向對不同的列進行排序。例如,按升序對動物的種類進行排序,然后按降序根據生日對各動物種類進行排序(最年輕的動物在最前面),使用下列查詢:
mysql> SELECT name, species, birth FROM pet -> ORDER BY species, birth DESC; +----------+---------+------------+| name | species | birth |+----------+---------+------------+| Chirpy | bird | 1998-09-11 || Whistler | bird | 1997-12-09 || Claws | cat | 1994-03-17 || Fluffy | cat | 1993-02-04 || Fang | dog | 1990-08-27 || Bowser | dog | 1989-08-31 || Buffy | dog | 1989-05-13 || Puffball | hamster | 1999-03-30 || Slim | snake | 1996-04-29 |+----------+---------+------------+
注意DESC關鍵字僅適用于在它前面的列名(birth);不影響species列的排序順序。
5. 日期計算MySQL提供了幾個函數,可以用來計算日期,例如,計算年齡或提取日期部分。
要想確定每個寵物有多大,可以計算當前日期的年和出生日期之間的差。如果當前日期的日歷年比出生日期早,則減去一年。以下查詢顯示了每個寵物的出生日期、當前日期和年齡數值的年數字。
mysql> SELECT name, birth, CURDATE(), -> (YEAR(CURDATE())-YEAR(birth)) -> - (RIGHT(CURDATE(),5)<RIGHT(birth,5)) -> AS age -> FROM pet; +----------+------------+------------+------+| name | birth | CURDATE() | age |+----------+------------+------------+------+| Fluffy | 1993-02-04 | 2003-08-19 | 10 || Claws | 1994-03-17 | 2003-08-19 | 9 || Buffy | 1989-05-13 | 2003-08-19 | 14 || Fang | 1990-08-27 | 2003-08-19 | 12 || Bowser | 1989-08-31 | 2003-08-19 | 13 || Chirpy | 1998-09-11 | 2003-08-19 | 4 || Whistler | 1997-12-09 | 2003-08-19 | 5 || Slim | 1996-04-29 | 2003-08-19 | 7 || Puffball | 1999-03-30 | 2003-08-19 | 4 |+----------+------------+------------+------+
此處,YEAR()提取日期的年部分,RIGHT()提取日期的MM-DD (日歷年)部分的最右面5個字符。比較MM-DD值的表達式部分的值一般為1或0,如果CURDATE()的年比birth的年早,則年份應減去1。整個表達式有些難懂,使用alias (age)來使輸出的列標記更有意義。
盡管查詢可行,如果以某個順序排列行,則能更容易地瀏覽結果。添加ORDER BY name子句按照名字對輸出進行排序則能夠實現。
mysql> SELECT name, birth, CURDATE(), -> (YEAR(CURDATE())-YEAR(birth)) -> - (RIGHT(CURDATE(),5)<RIGHT(birth,5)) -> AS age
-> FROM pet ORDER BY name;+----------+------------+------------+------+| name | birth | CURDATE() | age |+----------+------------+------------+------+| Bowser | 1989-08-31 | 2003-08-19 | 13 || Buffy | 1989-05-13 | 2003-08-19 | 14 || Chirpy | 1998-09-11 | 2003-08-19 | 4 || Claws | 1994-03-17 | 2003-08-19 | 9 || Fang | 1990-08-27 | 2003-08-19 | 12 || Fluffy | 1993-02-04 | 2003-08-19 | 10 || Puffball | 1999-03-30 | 2003-08-19 | 4 || Slim | 1996-04-29 | 2003-08-19 | 7 || Whistler | 1997-12-09 | 2003-08-19 | 5 |+----------+------------+------------+------+
為了按age而非name排序輸出,只要再使用一個ORDER BY子句:
mysql> SELECT name, birth, CURDATE(), -> (YEAR(CURDATE())-YEAR(birth)) -> - (RIGHT(CURDATE(),5)<RIGHT(birth,5)) -> AS age -> FROM pet ORDER BY age; +----------+------------+------------+------+| name | birth | CURDATE() | age |+----------+------------+------------+------+| Chirpy | 1998-09-11 | 2003-08-19 | 4 || Puffball | 1999-03-30 | 2003-08-19 | 4 || Whistler | 1997-12-09 | 2003-08-19 | 5 || Slim | 1996-04-29 | 2003-08-19 | 7 || Claws | 1994-03-17 | 2003-08-19 | 9 || Fluffy | 1993-02-04 | 2003-08-19 | 10 || Fang | 1990-08-27 | 2003-08-19 | 12 || Bowser | 1989-08-31 | 2003-08-19 | 13 || Buffy | 1989-05-13 | 2003-08-19 | 14 |+----------+------------+------------+------+
可以使用一個類似的查詢來確定已經死亡動物的死亡年齡。你通過檢查death值是否是NULL來確定是哪些動物,然后,對于那些非NULL值的動物,需要計算出death和birth值之間的差:
mysql> 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; +--------+------------+------------+------+| name | birth | death | age |+--------+------------+------------+------+| Bowser | 1989-08-31 | 1995-07-29 | 5 |+--------+------------+------------+------+
查詢使用death IS NOT NULL而非death != NULL,因為NULL是特殊的值,不能使用普通比較符來比較,以后會給出解釋。
如果你想要知道哪個動物下個月過生日,怎么辦?對于這類計算,年和天是無關的,你只需要提取birth列的月份部分。MySQL提供幾個日期部分的提取函數,例如YEAR( )、MONTH( )和DAYOFMONTH( )。在這里MONTH()是適合的函數。為了看它怎樣工作,運行一個簡單的查詢,顯示birth和MONTH(birth)的值:
mysql> SELECT name, birth, MONTH(birth) FROM pet; +----------+------------+--------------+| name | birth | MONTH(birth) |+----------+------------+--------------+| Fluffy | 1993-02-04 | 2 || Claws | 1994-03-17 | 3 || Buffy | 1989-05-13 | 5 || Fang | 1990-08-27 | 8 || Bowser | 1989-08-31 | 8 || Chirpy | 1998-09-11 | 9 || Whistler | 1997-12-09 | 12 || Slim | 1996-04-29 | 4 || Puffball | 1999-03-30 | 3 |+----------+------------+--------------+
找出下個月生日的動物也是容易的。假定當前月是4月,那么月值是4,你可以找在5月出生的動物 (5月),方法是:
mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = 5; +-------+------------+| name | birth |+-------+------------+| Buffy | 1989-05-13 |+-------+------------+
如果當前月份是12月,就有點復雜了。你不能只把1加到月份數(12)上并尋找在13月出生的動物,因為沒有這樣的月份。相反,你應尋找在1月出生的動物(1月) 。
你甚至可以編寫查詢,不管當前月份是什么它都能工作。采用這種方法不必在查詢中使用一個特定的月份,DATE_ADD( )允許在一個給定的日期上加上時間間隔。如果在NOW( )值上加上一個月,然后用MONTH()提取月份,結果產生生日所在月份:
mysql> SELECT name, birth FROM pet -> WHERE MONTH(birth) = MONTH(DATE_ADD(CURDATE(),INTERVAL 1 MONTH));
完成該任務的另一個方法是加1以得出當前月份的下一個月(在使用取模函數(MOD)后,如果月份當前值是12,則“回滾”到值0):
mysql> 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)。
6. NULL值操作NULL值可能令人感到奇怪直到你習慣它。概念上,NULL意味著“沒有值”或“未知值”,且它被看作與眾不同的值。為了測試NULL,你不能使用算術比較 操作符例如=、<或!=。為了說明它,試試下列查詢:
mysql> SELECT 1 = NULL, 1 <> NULL, 1 < NULL, 1 > NULL; +----------+-----------+----------+----------+| 1 = NULL | 1 <> NULL | 1 < NULL | 1 > NULL |+----------+-----------+----------+----------+| NULL | NULL | NULL | NULL |+----------+-----------+----------+----------+
很顯然你不能通過這些比較得到有意義的結果。相反使用IS NULL和IS NOT NULL操作符:
mysql> SELECT 1 IS NULL, 1 IS NOT NULL; +-----------+---------------+| 1 IS NULL | 1 IS NOT NULL |+-----------+---------------+| 0 | 1 |+-----------+---------------+
請注意在MySQL中,0或 NULL意味著假而其它值意味著真。布爾運算的默認真值是1。
對NULL的特殊處理即是在前面的章節中,為了決定哪個動物不再是活著的,使用death IS NOT NULL而不使用death != NULL的原因。
在GROUP BY中,兩個NULL值視為相同。
執行ORDER BY時,如果運行 ORDER BY ... ASC,則NULL值出現在最前面,若運行ORDER BY ... DESC,則NULL值出現在最后面。
NULL操作的常見錯誤是不能在定義為NOT NULL的列內插入0或空字符串,但事實并非如此。在NULL表示'沒有數值'的地方有數值。使用IS [NOT] NULL則可以很容易地進行測試,如下所示:
mysql> SELECT 0 IS NULL, 0 IS NOT NULL, ’’ IS NULL, ’’ IS NOT NULL; +-----------+---------------+------------+----------------+| 0 IS NULL | 0 IS NOT NULL | ’’ IS NULL | ’’ IS NOT NULL |+-----------+---------------+------------+----------------+| 0 | 1 | 0 | 1 |+-----------+---------------+------------+----------------+
因此完全可以在定義為NOT NULL的列內插入0或空字符串,實際是NOT NULL。
7. 模式匹配MySQL提供標準的SQL模式匹配,以及一種基于象Unix實用程序如vi、grep和sed的擴展正則表達式模式匹配的格式。
SQL模式匹配允許你使用
“_”匹配任何單個字符,而
“%”匹配任意數目字符(包括零字符)。在 MySQL中,SQL的模式默認是忽略大小寫的。下面給出一些例子。注意使用SQL模式時,不能使用=或!=;而應使用LIKE或NOT LIKE比較操作符。
要想找出以
“b”開頭的名字:
mysql> SELECT * FROM pet WHERE name LIKE ’b%’; +--------+--------+---------+------+------------+------------+| name | owner | species | sex | birth | death |+--------+--------+---------+------+------------+------------+| Buffy | Harold | dog | f | 1989-05-13 | NULL || Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 |+--------+--------+---------+------+------------+------------+
要想找出以
“fy”結尾的名字:
mysql> SELECT * FROM pet WHERE name LIKE ’%fy’; +--------+--------+---------+------+------------+-------+| name | owner | species | sex | birth | death |+--------+--------+---------+------+------------+-------+| Fluffy | Harold | cat | f | 1993-02-04 | NULL || Buffy | Harold | dog | f | 1989-05-13 | NULL |+--------+--------+---------+------+------------+-------+
要想找出包含
“w”的名字:
mysql> SELECT * FROM pet WHERE name LIKE ’%w%’; +----------+-------+---------+------+------------+------------+| name | owner | species | sex | birth | death |+----------+-------+---------+------+------------+------------+| Claws | Gwen | cat | m | 1994-03-17 | NULL || Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 || Whistler | Gwen | bird | NULL | 1997-12-09 | NULL |+----------+-------+---------+------+------------+------------+
要想找出正好包含5個字符的名字,使用
“_”模式字符:
mysql> SELECT * FROM pet WHERE name LIKE ’_____’; +-------+--------+---------+------+------------+-------+| name | owner | species | sex | birth | death |+-------+--------+---------+------+------------+-------+| Claws | Gwen | cat | m | 1994-03-17 | NULL || Buffy | Harold | dog | f | 1989-05-13 | NULL |+-------+--------+---------+------+------------+-------+
由MySQL提供的模式匹配的其它類型是使用擴展正則表達式。當你對這類模式進行匹配測試時,使用REGEXP和NOT REGEXP操作符(或RLIKE和NOT 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’; +--------+--------+---------+------+------------+------------+| name | owner | species | sex | birth | death |+--------+--------+---------+------+------------+------------+| Buffy | Harold | dog | f | 1989-05-13 | NULL || Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 |+--------+--------+---------+------+------------+------------+
如果你想強制使REGEXP比較區分大小寫,使用BINARY關鍵字使其中一個字符串變為二進制字符串。該查詢只匹配名稱首字母的小寫‘b’。
mysql> SELECT * FROM pet WHERE name REGEXP BINARY ’^b’;
為了找出以
“fy”結尾的名字,使用
“$”匹配名字的結尾:
mysql> SELECT * FROM pet WHERE name REGEXP ’fy$’; +--------+--------+---------+------+------------+-------+| name | owner | species | sex | birth | death |+--------+--------+---------+------+------------+-------+| Fluffy | Harold | cat | f | 1993-02-04 | NULL || Buffy | Harold | dog | f | 1989-05-13 | NULL |+--------+--------+---------+------+------------+-------+
為了找出包含一個
“w”的名字,使用以下查詢:
mysql> SELECT * FROM pet WHERE name REGEXP ’w’; +----------+-------+---------+------+------------+------------+| name | owner | species | sex | birth | death |+----------+-------+---------+------+------------+------------+| Claws | Gwen | cat | m | 1994-03-17 | NULL || Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 || Whistler | Gwen | bird | NULL | 1997-12-09 | NULL |+----------+-------+---------+------+------------+------------+
既然如果一個正則表達式出現在值的任何地方,其模式匹配了,就不必在先前的查詢中在模式的兩側放置一個通配符以使得它匹配整個值,就像你使用了一個SQL模式那樣。
為了找出包含正好5個字符的名字,使用
“^”和
“$”匹配名字的開始和結尾,和5個
“.”實例在兩者之間:
mysql> SELECT * FROM pet WHERE name REGEXP ’^.....$’; +-------+--------+---------+------+------------+-------+| name | owner | species | sex | birth | death |+-------+--------+---------+------+------------+-------+| Claws | Gwen | cat | m | 1994-03-17 | NULL || Buffy | Harold | dog | f | 1989-05-13 | NULL |+-------+--------+---------+------+------------+-------+
你也可以使用
“{n}”“重復n次”操作符重寫前面的查詢:
mysql> SELECT * FROM pet WHERE name REGEXP ’^.{5}$’; +-------+--------+---------+------+------------+-------+| name | owner | species | sex | birth | death |+-------+--------+---------+------+------------+-------+| Claws | Gwen | cat | m | 1994-03-17 | NULL || Buffy | Harold | dog | f | 1989-05-13 | NULL |+-------+--------+---------+------+------------+-------+8. 計數行
數據庫經常用于回答這個問題,“某個類型的數據在表中出現的頻度?”例如,你可能想要知道你有多少寵物,或每位主人有多少寵物,或你可能想要對你的動物進行各種類型的普查。計算你擁有動物的總數目與“在pet表中有多少行?”是同樣的問題,因為每個寵物有一個記錄。COUNT(*)函數計算行數,所以計算動物數目的查詢應為:
mysql> SELECT COUNT(*) FROM pet; +----------+| COUNT(*) |+----------+|9 |+----------+
在前面,你檢索了擁有寵物的人的名字。如果你想要知道每個主人有多少寵物,你可以使用COUNT( )函數:
mysql> SELECT owner, COUNT(*) FROM pet GROUP BY owner; +--------+----------+| owner | COUNT(*) |+--------+----------+| Benny |2 || Diane |2 || Gwen |3 || Harold |2 |+--------+----------+
注意,使用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; +---------+----------+| species | COUNT(*) |+---------+----------+| bird |2 || cat |2 || dog |3 || hamster |1 || snake |1 |+---------+----------+
每種性別的動物數量:
mysql> SELECT sex, COUNT(*) FROM pet GROUP BY sex; +------+----------+| sex | COUNT(*) |+------+----------+| NULL |1 || f |4 || m |4 |+------+----------+
(在這個輸出中,NULL表示“未知性別”。)
按種類和性別組合的動物數量:
mysql> SELECT species, sex, COUNT(*) FROM pet GROUP BY species, sex; +---------+------+----------+| species | sex | COUNT(*) |+---------+------+----------+| bird | NULL |1 || bird | f |1 || cat | f |1 || cat | m |1 || dog | f |1 || dog | m |2 || hamster | f |1 || snake | m |1 |+---------+------+----------+
若使用COUNT( ),你不必檢索整個表。例如, 前面的查詢,當只對狗和貓進行時,應為:
mysql> SELECT species, sex, COUNT(*) FROM pet -> WHERE species = ’dog’ OR species = ’cat’ -> GROUP BY species, sex; +---------+------+----------+| species | sex | COUNT(*) |+---------+------+----------+| cat | f |1 || cat | m |1 || dog | f |1 || dog | m |2 |+---------+------+----------+
或,如果你僅需要知道已知性別的按性別的動物數目:
mysql> SELECT species, sex, COUNT(*) FROM pet -> WHERE sex IS NOT NULL -> GROUP BY species, sex; +---------+------+----------+| species | sex | COUNT(*) |+---------+------+----------+| bird | f |1 || cat | f |1 || cat | m |1 || dog | f |1 || dog | m |2 || hamster | f |1 || snake | m |1 |+---------+------+----------+9. 使用1個以上的表
pet表追蹤你有哪個寵物。如果你想要記錄其它相關信息,例如在他們一生中看獸醫或何時后代出生,你需要另外的表。這張表應該像什么呢?需要:· 它需要包含寵物名字以便你知道每個事件屬于哪個動物。
· 需要一個日期以便你知道事件是什么時候發生的。
· 需要一個描述事件的字段。
· 如果你想要對事件進行分類,則需要一個事件類型字段。
綜合上述因素,event表的CREATE TABLE語句應為:
mysql> CREATE TABLE event (name VARCHAR(20), date DATE, -> type VARCHAR(15), remark VARCHAR(255));
對于pet表,最容易的方法是創建包含信息的用定位符分隔的文本文件來裝載初始記錄:
namedatetyperemarkFluffy1995-05-15litter4 kittens, 3 female, 1 maleBuffy1993-06-23litter5 puppies, 2 female, 3 maleBuffy1994-06-19litter3 puppies, 3 femaleChirpy1999-03-21vetneeded beak straightenedSlim1997-08-03vetbroken ribBowser1991-10-12kennelFang1991-10-12kennelFang1998-08-28birthdayGave him a new chew toyClaws1998-03-17birthdayGave him a new flea collarWhistler1998-12-09birthdayFirst birthday采用如下方式裝載記錄:
mysql> LOAD DATA LOCAL INFILE ’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’; +--------+------+-----------------------------+| name | age | remark |+--------+------+-----------------------------+| Fluffy | 2 | 4 kittens, 3 female, 1 male || Buffy | 4 | 5 puppies, 2 female, 3 male || Buffy | 5 | 3 puppies, 3 female |+--------+------+-----------------------------+
關于該查詢要注意的幾件事情:
FROM子句列出兩個表,因為查詢需要從兩個表提取信息。當從多個表組合(聯結)信息時,你需要指定一個表中的記錄怎樣能匹配其它表的記錄。這很簡單,因為它們都有一個name列。查詢使用WHERE子句基于name值來匹配2個表中的記錄。因為name列出現在兩個表中,當引用列時,你一定要指定哪個表。把表名附在列名前即可以實現。你不必有2個不同的表來進行聯結。如果你想要將一個表的記錄與同一個表的其它記錄進行比較,可以將一個表聯結到自身。例如,為了在你的寵物之中繁殖配偶,你可以用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’; +--------+------+--------+------+---------+| name | sex | name | sex | species |+--------+------+--------+------+---------+| Fluffy | f | Claws | m | cat || Buffy | f | Fang | m | dog || Buffy | f | Bowser | m | dog |+--------+------+--------+------+---------+
在這個查詢中,我們為表名指定別名以便能引用列并且使得每一個列引用與哪個表實例相關聯更直觀。
相關文章: