MySQL數據庫基礎(筆記整理三)
檢索信息
SELECT語句允許以你喜歡的方式檢索和顯示數據表裏的信息。通常SELECT語句由以下幾個部分組成:
SELECT what to retrieve
FORM table or tables
WHERE conditions that data must satisfy;
在寫SELECT語句時,盡量把你想檢索的東西描述清楚,再把可選子句寫出來。(FROM和WHERE就是比較常見的兩個子句),其他子句包括GROUP BY、ORDER BY和LIMIT等。
有趣的是,SQL語句對書寫格式的要求並沒有Shell或大多數編程語言那麽嚴格,所以你在書寫SELECT語句時,選擇換行符的位置以及大小寫的要求時完全可以按照你的個人習慣來書寫,但是良好的書寫習慣會使SQL語句的閱讀性和後期的數據庫維護更便捷。
FROM子句一般不能省略(你要指定從哪個數據表檢索數據),但SELECT 當操作不涉及數據表時,完全沒有必要把FROM子句寫出來,例如:
mysql> SECLECT 2+2, ‘Hello, World!‘, VERSION();
MySQL允許把表達式的計算結果當做輸出列的值,而不引用數據表。但是,當你明確需要使用哪個數據表檢索數據時,應該用FROM子句指定數據表,當然還需要把想要查看的數據列的名字列舉出來。例如:
mysql> SELECT * FROM student;
上面這條查詢將把student數據表的所有數據列全部顯示出來。(當然,檢索時應盡量避免 * 的使用)想要查詢某一列的數據時,在SELECT後把數據列的名字逐個列出來就行,多個數據列之間用逗號隔開。例如:
mysql> SELECT name, student_id FROM student;
上面提到過SQL語句對於大小寫並沒有嚴格的要求,但是需要註意的是,數據表的名字和數據庫的名字可能需要區分大小寫。(比如,在Linux系統上數據表和數據庫的名字是嚴格區分大小寫的)
指定檢索條件
想要完成更為精確的查詢,需要給SELECT語句加上一個WHERE子句來篩選你想要的數據。例如:
mysql> SELECT * FROM score WHERE score > 95;
或者匹配某一特定行的記錄:
mysql> SELECT name, city FROM student WHERE student_id = ‘2017011111‘ ;
WHERE子句裏的表達式允許使用算術運算符、比較運算符和邏輯運算符,你可以靈活的使用常數、數據表的數據列和函數調用進行運算。例如:
mysql> SELECT name, birth , city, score FROM student
-> WHERE birth < ‘1999-10-10‘ AND city IN(‘長春‘ , ‘吉林‘) ;
上面的這條查詢的意思是,從student表中找出家在長春或者吉林並且出生日期早於1999年10月10日的同學,並把他們的姓名、生日、籍貫、分數列出來。在這條查詢中,用IN()操 作符來查找幾個值中的某一個會很方便。
NULL 值
NULl值是一個很特殊的值。它的含義是缺省(無數據或者未知數據),所以不能用它與“有數據”的值進行運算或者比較。如果需要對NULL值進行查找,就必須使用IS NULL 或IS NOT NULL 來判斷。例如:在一張記錄學生成績的表中把缺考的學生找出來:
mysql> SELECT name, student_id, score FROM student_exam
-> WHERE score IS NUll;
當然使用MySQL專用的比較操作符 <=> 也能完成NULL值與NULL 值之間的比較。上面的查詢可以改為:
mysql> SELECT name, student_id, score FROM student_exam
-> WHERE NOT( score <=> NULL);
需要註意的是,NULL值與0或者空字符串`` “” ``並不相等。
對查詢結果進行排序
雖然數據記錄在查詢結果中的先後順序通常與他們在當初被插入時的先後順序一致。但如果數據表一旦經過增刪改查等一些操作後,這些操作往往會改變數據行在服務器所返回的數據表檢索結果中的先後順序。所以,除非你能夠保證從服務器返回的數據事先沒有經過任何變動。否則,想讓查詢結果返回你希望的先後順序顯示,就必須給查詢命令增加一條ORDER BY 子句。例如:
mysql> SELECT name, student_id, sex, score FROM
-> student ORDER BY score;
ORDER BY子句默認的排序方式是升序(ASC),在ORDER BY 子句中的數據列名字後面加上DESC則表示按降序排列。也可以對查詢結果的多個數據列進行排序,而每一個數據列又都可以互不影響地分別按升序或降序進行排列。例如:
mysql> SELECT name, student_id, score, sex, city
-> FROM student ORDER BY score DESC, student_id ASC;
對於包含NULL的數據行,如果設定按升序排列,他們將出現在查詢的開頭;如果設定按降序排列,他們將出現在查詢結果的末尾。
限制查詢結果中的數據行個數
查詢結果往往由很多數據行構成,如果你只想要其中一小部分,可以可查詢命令增加一個LIMIT子句。ORDER BY 配合LIMIT 1
列出查詢中的排在第一行的那條結果。當然,你也可以指定從查詢結果中抽出一部分,此時必須指定兩個值,第一個值給出要在查詢結果的開頭部分跳過的數據記錄個數,第二個值則是需要返回的數據記錄個數。例如:
mysql> SELECT name, student_id, score
-> FROM student ORDER BY score DESC LIMIT 10, 5;
上面這條查詢返回成績排在11到15名的同學的信息。
對輸出列進行求值和命名
前面提到過MySQL允許把表達式的結果當做輸出列的值,而不引用數據表。數據表裏的數據列名字也可以用在表達式裏,例如:
mysql> SELECT CONCAT(student_id,‘ ‘, name) as stuinfo, CONCAT(city, ‘,‘ ,state)
-> FROM student;
在上面的查詢中, 我們對輸出咧的格式進行了設置:把學生的學號和姓名合起來顯示(以空格分隔),城市和省份也合起來輸出(以逗號分隔),並且在輸出結果中分別以別名顯示這兩列的標題。在為數據列提供別名時,關鍵字AS可以省略,但是如果省略它稍不留神可能會出現錯誤,例如:
mysql> SELECT name city FROM student;
上面的查詢本意是查詢學生的姓名和籍貫,但是漏了name和city數據列之間的逗號,於是city將被視為name的別名從而成為了輸出列的表頭。
與日期相關的問題
MySQL中常見的有關日期的操作,有下面幾種:
- 按日期排序
- 查找某個日期或者某個日期範圍
- 提取日期中的年、月、日等組成部分
- 計算兩個日期之間的時間距離
- 用一個日期加上或減去一個時間間隔以求出另一個日期
# 1.
mysql> SELECT * FROM student WHERE date = ‘2018-10-10‘ ;
# 2.
mysql> SELECT * FROM student WHERE date >= ‘2018-10-01‘ AND date < ‘ 2018-10-13‘ ;
# 3. 日期中的年、 月、 日可以用函數 YEAR() 、 MONTH()、 DAYOFMONTH() 分別提取出來。
mysql> SELECT * FROM student WHERE MONTH(birth) = 3; # 把生日在3月的同學列出來,也可以用MONTHNAME(birth) = ‘March‘
#4. 生日在同一天的同學,不一定同年。(所以可以用DAYOFMONTH)
mysql> SELECT * FROM student WHERE MONTH(birth) = 3 AND DAYOFMONTH(birth) = 29;
#5.
mysql> SELECT name, city, TIMESTAMPDIFF(YEAR, birth,CURDATE()) as age FROM student
-> WHERE birth IS NOT NULL ORDER BY age DESC LIMIT 1;
模式匹配
MySQL支持模式匹配操作,這使得我們能夠在沒有給出精確比較值的情況下把有關的數據行檢索出來,模式匹配用(LIKE和NOT LIKE 操作符),還需要你提供一個包含通配符的字符串。_
只能匹配一個字符, %
能匹配零到任意字符序列。例如:
mysql> SELECT name, city, student_id FROM student WHERE student_id LIKE ‘1%‘ ;
mysql> SELECT name, city , student_id FROM WHERE city LIKE ‘__‘;
MySQL還提供基於正則表達式和REGEXP
操作符的另一種更為靈活和強大的匹配形式。例如:
mysql> SELECT name, city , student_id, sex FROM WHERE city REGEXP ‘^吉’ ;
# 把籍貫以吉開頭的同學的信息列出來
# 更多關於正則表達是的知識,可以參考我關於正則表達是的筆記
設置和使用SQL變量
MySQL允許自定義變量。我們可以使用查詢結果來設置變量,這使我們能夠方便地把一些值保存起來以供今後查詢。
mysql> SELECT @score := score FROM student WHERE score = 60 ;
mysql> SELECT name, student_id , score FROM student
-> WHERE score > @score ORDER BY score DESC;
變量額命名語法是“@變量名” ,賦值語法是在SELECT語句裏使用一個“@變量名:= 值” 形式的表達式。其實上面的查詢可以通過一個聯結或子查詢語句得到,稍後我們會看到。
SET語句也能用來對變量賦值。
mysql> SET @today := CURDATE() ;
生成計數信息
MySQL最有用的功能之一是它能夠依據大量未經加工的數據生成多種統計匯總信息。找出一組數據裏到底有多少種不同的取值是一項比較常見的統計工作,而關鍵字DISTINCT恰好能讓我們把在查詢結果中重復出現的數據行清除掉。例如:
mysql> SELECT DISTINCT city FROM student ORDER BY city;
上面的查詢把學生籍貫不加重復的列舉出來。另一個比較常見的統計工作是利用COUNT() 函數來計數。COUNT(*)能把你的查詢到底選取了多少數據行做一個統計。例如:
mysql> SELECT COUNT(*) FROM student WHERE score <60 ;
上面的查詢返回成績不及格的同學的人數。COUNT(*)的統計結果是被選中的數據行的總數,而COUNT(數據列名稱)值則只統計全體非NULL值的個數。COUNT()可以和DISTINCT連用,用以統計有多少不同的非NULL值。例如:
mysql> SELECT COUNT(DISTINCT city) FROM student;
上面的查詢可以統計出學生數據表中到底有多少不同的城市個數。COUNT()函數和WHERE子句連用,可以篩選出不同類型的個數。例如:
mysql> SELECT COUNT(*) FROM student WHERE sex = ‘F‘;
mysql> SELECT COUNT(*) FROM student WHERE sex = ‘M‘;
事實上上面的查詢可以用更為方便的GROUP BY子句進行分類,MySQL可以只用一個查詢就把某數據列裏的不同值分別出現過多少次的情況統計出來。上面的例子可以做如下修改,例如:
mysql> SELECT sex, COUNT(*) AS 人數 FROM student GROUP BY sex ;
如果需要進行這種分門別類的統計,GROUP BY子句是必不可少的選擇,它的作用是讓MySQL知道在統計之前應該如何對有關的數據記錄分類。與反復使用多個彼此近似的查詢來分別統計某數據列不同取值出現次數的做法相比,把COUNT(*)函數與GROUP BY子句相結合的做法有很多有點:
- 在開始統計之前,我們不必知道將被統計的數據列不同取值出現次數到底有多少種不同的取值
- 我們只需要使用一個而不是好幾個查詢
- 因為只用一個查詢就能把所有的結果都查出來,所以我們還能對輸出進行排序
前兩個優點有助於簡化查詢語句的書寫,而第三個優點它能讓我們更加靈活地顯示查詢結果。例如:
mysql> SELECT city, COUNT(*) AS 人數 FROM student GROUP BY city ORDER BY 人數 DESC;
上面的查詢把學生表中分別來自什麽城市做一個分類,統計數量後按降序排序。(來自哪個地方的學生最多) 如果你打算用ORDER BY 子句對一個計算出來的結果進行歸類,可以使用輸出列的別名或者它們在查詢結果裏的出現位置來設定(不推薦,也不屬於標準SQL的一部分)。例如:
mysql> SELECT MONTH(birth) AS Month, MONTHNAME(birth) AS name, COUNT(*) AS 人數
-> FROM student GROUP BY name ORDER BY Month;
同樣,COUNT()函數還能與ORDER BY 和LIMIT子句聯合使用。而想要把與某個特定COUNT()值相對應的記錄找出來,需要使用HAVING子句。(WHERE和HAVING,簡單地可以理解為一個在分組前篩選數據[WHERE],一個在分組後篩選數據[HAVING],WHERE後面不能跟聚合函數)例如:
mysql> SELECT city, COUNT(*) AS 人數 FROM student GROUP city HAVING 人數 > 2 ORDER BY 人數 DESC;
除COUNT()以外,MySQL還有其他一些匯總函數。(MIN()、MAX()、SUM()和AVG()..) 要讓MySQL對數據行分組統計結果做進一步的統計得到所謂的 “超級聚合” 值。加上WITH ROLLUP 子句即可。例如:
mysql> SELECT sex, COUNT(*) FROM student GROUP BY sex WITH ROLLUP;
上面這條查詢將對兩種性別的學生人數進行匯總並生成一行輸出。
2017/10/13 數據庫基礎筆記 (三)
MySQL數據庫基礎(筆記整理三)