日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

《SQL必知必会》读书笔记上(第1~15章)

發(fā)布時(shí)間:2023/12/20 数据库 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《SQL必知必会》读书笔记上(第1~15章) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

第1章 了解SQL

第2章 MySQL簡(jiǎn)介

第3章 使用MySQL

3.1 連接數(shù)據(jù)庫(kù)

3.2 選擇數(shù)據(jù)庫(kù)

3.3 顯示數(shù)據(jù)庫(kù)和表

3.4 其他SHOW語(yǔ)句

第4章 檢索數(shù)據(jù)

4.1 SELECT語(yǔ)句

4.2 檢索單個(gè)列

4.3 檢索多個(gè)列

4.4 檢索所有列

4.5 檢索不同的行(去重)

4.6 限制結(jié)果

4.7 使用完全限定名

第5章 排序檢索數(shù)據(jù)

5.1 排序數(shù)據(jù)

5.2 按多個(gè)列排序

5.3 指定排序方向

第6章 過(guò)濾數(shù)據(jù)

6.1 使用WHERE子句

6.2 WHERE子句操作符

第7章 數(shù)據(jù)過(guò)濾

7.1 組合WHERE子句

7.1.1 AND操作符

7.1.2 OR操作符

7.1.3 計(jì)算次序

7.2 IN操作符

7.3 NOT操作符

第8章 用通配符進(jìn)行過(guò)濾

8.1 LIKE操作符

8.1.1 百分號(hào)(%)通配符

8.1.2 下劃線(_)通配符

8.2 使用通配符的技巧

第9章 用正則表達(dá)式進(jìn)行搜索

9.1 正則表達(dá)式介紹

9.2 使用MySQL正則表達(dá)式

9.2.1 基本字符匹配

9.2.2 進(jìn)行OR匹配

9.2.3 匹配幾個(gè)字符之一

9.2.4 匹配范圍

9.2.5 匹配特殊字符

9.2.6 匹配字符類

9.2.7 匹配多個(gè)實(shí)例

9.2.8 定位符

第10章 創(chuàng)建計(jì)算字段

10.1 計(jì)算字段

10.2 拼接字段

10.3 執(zhí)行算術(shù)運(yùn)算

第11章 使用數(shù)據(jù)處理函數(shù)

11.1 函數(shù)

11.2 使用函數(shù)

11.2.1 文本處理函數(shù)

11.2.2 日期和時(shí)間處理函數(shù)

11.2.3 數(shù)值處理函數(shù)

第12章 匯總數(shù)據(jù)

12.1 聚集函數(shù)

12.1.1 AVG()函數(shù)

12.1.2 COUNT()函數(shù)

12.1.3 MAX()函數(shù)

12.1.4 MIN()函數(shù)?

12.1.5 SUM()函數(shù)

12.2 聚集不同值

12.3 組合聚集函數(shù)

第13章 分組數(shù)據(jù)

13.1 分組

13.2 創(chuàng)建分組

13.3 過(guò)濾分組

13.4 分組和排序

13.5 SELECT子句順序

第14章 使用子查詢

14.1 子查詢

14.2 利用子查詢進(jìn)行過(guò)濾

14.3 作為計(jì)算字段使用子查詢

第15章 聯(lián)結(jié)表

15.1 聯(lián)結(jié)

15.1.1 關(guān)系表

15.1.2 為什么要使用聯(lián)結(jié)

15.2 創(chuàng)建聯(lián)結(jié)

15.2.1 WHERE子句的重要性

15.2.2 內(nèi)部聯(lián)結(jié)

15.2.3 聯(lián)結(jié)多個(gè)表



第1章 了解SQL

第1章最值得注意的就是關(guān)于數(shù)據(jù)庫(kù)的相關(guān)概念。

  • 數(shù)據(jù)庫(kù)(Database):保存有組織的數(shù)據(jù)的容器。也可以理解成保存有數(shù)據(jù)的倉(cāng)庫(kù)。

注意:數(shù)據(jù)庫(kù)Database和數(shù)據(jù)庫(kù)管理系統(tǒng)DBMS是有區(qū)別的,但人們常用數(shù)據(jù)庫(kù)這個(gè)術(shù)語(yǔ)來(lái)表示他們所用的數(shù)據(jù)庫(kù)軟件(也就是數(shù)據(jù)庫(kù)管理系統(tǒng))。例如我們常說(shuō)我們使用的是MySQL數(shù)據(jù)庫(kù),這其實(shí)是不嚴(yán)謹(jǐn)?shù)?#xff0c;因?yàn)镸ySQL是數(shù)據(jù)庫(kù)軟件。數(shù)據(jù)庫(kù)是通過(guò)DBMS創(chuàng)建和操作的容器,但其實(shí)數(shù)據(jù)庫(kù)是什么不重要,因?yàn)槲覀儾荒苤苯釉L問(wèn),需要通過(guò)DBMS間接訪問(wèn)到數(shù)據(jù)庫(kù)。

  • 表(Table):是某種特定類型數(shù)據(jù)的結(jié)構(gòu)化清單。例如顧客清單,學(xué)校的所有學(xué)生,公司的所有員工等。

注意:所謂表的特定類型數(shù)據(jù)即學(xué)校的學(xué)生和公司的員工不應(yīng)該存儲(chǔ)在同一張數(shù)據(jù)庫(kù)表中,這會(huì)使得以后的訪問(wèn)很困難,應(yīng)該創(chuàng)建兩張表即學(xué)生表和員工表。數(shù)據(jù)庫(kù)中的每個(gè)表有唯一的一個(gè)名字,但在不同的數(shù)據(jù)庫(kù)中又可以有相同的表名。例如:

  • 列(Column):是表中的一個(gè)字段,所有表都是一個(gè)或多個(gè)列組成的。

注意:理解列的最好方式就是將數(shù)據(jù)庫(kù)表想象稱為一個(gè)網(wǎng)格,網(wǎng)格中每一列都存儲(chǔ)著一條特定的信息。例如用戶表的列有id列、姓名列、密碼列、生日列等,如密碼列這一列都存儲(chǔ)的是密碼信息。

  • 數(shù)據(jù)類型(DataType):說(shuō)到列就必須說(shuō)到數(shù)據(jù)類型,即每列都有相應(yīng)的數(shù)據(jù)類型,它限制該列中所存儲(chǔ)的數(shù)據(jù)。

注意:數(shù)據(jù)類型是用來(lái)限制存儲(chǔ)的數(shù)據(jù)格式的,例如是生日列,那么該列應(yīng)該用日期類型,而不是整數(shù)類型。又可以用來(lái)防止用戶惡意錄入數(shù)據(jù),比如在生日列錄入他的名字。數(shù)據(jù)類型還可以幫助正確地排序數(shù)據(jù),優(yōu)化磁盤(pán)使用。例如:

  • 行(Row):表中的一條記錄。如果把表格想象成網(wǎng)格,那么網(wǎng)格中垂直的列為表列,水平的行為表行。

注意:其實(shí)行和記錄兩個(gè)術(shù)語(yǔ)是可以相互替代的。如學(xué)生表的每一行都存儲(chǔ)著一個(gè)學(xué)生的信息,而學(xué)生表的總行數(shù)表示共有多少個(gè)學(xué)生。例如:

  • 主鍵(Primary Key):一列(或一組列),其值能夠唯一區(qū)分表中的每個(gè)行。

注意:唯一標(biāo)識(shí)表中的每行的這個(gè)列(或這組列)稱為主鍵,如果沒(méi)有主鍵那么更新或刪除表中的特定行就會(huì)很困難。例如我國(guó)人民的身份證號(hào)就可以當(dāng)主鍵,因?yàn)樗麄兌际俏ㄒ坏?#xff0c;但會(huì)說(shuō)為什么不用人的姓名當(dāng)主鍵呢,因?yàn)槿珖?guó)人口那么多,重名的人數(shù)相當(dāng)多,如果要更新某個(gè)人的信息,通過(guò)姓名會(huì)找出許多條記錄,無(wú)法完成操作。通常我們會(huì)設(shè)定一個(gè)id來(lái)作為主鍵,如:

表中的任何列都可以作為主鍵,但需要滿足如下兩個(gè)條件:

(1)任意兩行都不具有相同的主鍵值。如用戶名列就不可以作為主鍵,因?yàn)榭赡苤孛?/p>

(2)每行都必須具有一個(gè)主鍵值,主鍵列不允許為NULL。

主鍵通常定義在表的一列上,但這并不是必需的,也可以一起使用多個(gè)列作為主鍵。在使用多列作為主鍵時(shí),上述條件必須應(yīng)用到構(gòu)成主鍵的所有列,所有列值的組合必須是唯一的(但單個(gè)列的值可以不唯一)。

  • SQL(Structured Query Language):即結(jié)構(gòu)化查詢語(yǔ)言,是一種專門(mén)用來(lái)與數(shù)據(jù)庫(kù)通信的語(yǔ)言。

注意:所謂的與數(shù)據(jù)庫(kù)通信就是對(duì)數(shù)據(jù)庫(kù)中的表和行進(jìn)行讀寫(xiě)操作。SQL是一種標(biāo)準(zhǔn),但不是所有的DBMS都遵循這種標(biāo)準(zhǔn),本書(shū)中是針對(duì)MySQL所講的。

SQL的優(yōu)點(diǎn)如下:

(1)SQL不是某個(gè)特定數(shù)據(jù)庫(kù)供應(yīng)商專有的語(yǔ)言。幾乎所有重要的DBMS(如MySQL、Oracle、SQL server等)都支持SQL,所以,學(xué)習(xí)此語(yǔ)言使你幾乎能與所有數(shù)據(jù)庫(kù)打交道。

(2)SQL簡(jiǎn)單易學(xué)。它的語(yǔ)句全都是由描述性很強(qiáng)的英語(yǔ)單詞組成,而且這些單詞的數(shù)目不多。

(3)SQL盡管看上去很簡(jiǎn)單,但它實(shí)際上是一種強(qiáng)有力的語(yǔ)言,靈活使用其語(yǔ)言元素,可以進(jìn)行非常復(fù)雜和高級(jí)的數(shù)據(jù)庫(kù)操作。

第2章 MySQL簡(jiǎn)介

MySQL:是一種數(shù)據(jù)庫(kù)管理系統(tǒng)(DBMS),即它是一種數(shù)據(jù)庫(kù)軟件,用來(lái)管理數(shù)據(jù)的。

MySQL的優(yōu)點(diǎn):

  • 成本——MySQL是開(kāi)放源代碼的,一般可以免費(fèi)使用(甚至可以免費(fèi)修改)。
  • 性能——MySQL執(zhí)行很快(非常快)。
  • 可信賴——某些非常重要和聲望很高的公司、站點(diǎn)使用MySQL,這些公司和站點(diǎn)都用MySQL來(lái)處理自己的重要數(shù)據(jù)。
  • 簡(jiǎn)單——MySQL很容易安裝和使用。

MySQL命令行實(shí)用程序:即在操作系統(tǒng)命令提示符下輸入mysql(或mysql -uroot -p)后出現(xiàn)的界面。

注意事項(xiàng):

  • 命令輸入在 mysql> 之后。
  • 命令用分號(hào) ; \g 結(jié)束,換句話說(shuō),僅按Enter不執(zhí)行命令。
  • 輸入 help\h 可以查看幫助,也可以輸入特定的命令查看特定幫助(如:help select查看select語(yǔ)句的幫助)
  • 輸入 quit exit 可以退出命令行使用程序。

圖形化工具:關(guān)于MySQL的圖形化工具推薦Navicat for MySQL等。

第3章 使用MySQL

3.1 連接數(shù)據(jù)庫(kù)

連接MySQL,需要如下幾個(gè)信息:

  • 主機(jī)名(計(jì)算機(jī)名)——如果連接到本地MySQL服務(wù)器,為 localhost;
  • 端口(如果使用默認(rèn)端口3306之外的端口);
  • 一個(gè)合法的用戶名;
  • 用戶口令(也就是密碼,如果需要)。

命令如下:

mysql -u 用戶名 -h 主機(jī)名 -P 端口號(hào) -p 密碼

3.2 選擇數(shù)據(jù)庫(kù)

這是必須的,因?yàn)镸ySQL可能管理著多個(gè)數(shù)據(jù)庫(kù),而不清楚你要用哪個(gè),所以必須用USE關(guān)鍵字選擇數(shù)據(jù)庫(kù)。語(yǔ)法:

# 選擇數(shù)據(jù)庫(kù) USE 數(shù)據(jù)庫(kù)名; # 查詢當(dāng)前處于哪個(gè)數(shù)據(jù)庫(kù)下 SELECT DATABASE();

3.3 顯示數(shù)據(jù)庫(kù)和表

可以通過(guò)下面的命令來(lái)查看有哪些數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)中有哪些表。

# 獲取MySQL內(nèi)部的所有數(shù)據(jù)庫(kù),以列表顯示返回 SHOW DATABASES; # 獲取當(dāng)前數(shù)據(jù)庫(kù)中的所有表,以列表顯示返回 SHOW TABLES; # 顯示指定數(shù)據(jù)庫(kù)中的所有表,以列表顯示返回 SHOW TABLES FROM 數(shù)據(jù)庫(kù)名; # 顯示某張表的列信息 SHOW COLUMNS FROM 表名; # 同上條語(yǔ)句功能一樣,也是顯示表的信息 DESCRIBE 表名; DESC 表名;

3.4 其他SHOW語(yǔ)句

所支持的其他 SHOW 語(yǔ)句還有(下面這些不常用,了解即可):

# 顯示廣泛的服務(wù)器狀態(tài)信息 SHOW STATUS; # 顯示創(chuàng)建特定的數(shù)據(jù)庫(kù) SHOW CREATE DATABASE 數(shù)據(jù)庫(kù)名; # 顯示創(chuàng)建特定的表 SHOW CREATE TABLE 表名; # 顯示授權(quán)用戶的安全權(quán)限 SHOW GRANTS; # 顯示服務(wù)器錯(cuò)誤信息 SHOW ERRORS; # 顯示服務(wù)器警告信息 SHOW WARNINGS;

第4章 檢索數(shù)據(jù)

4.1 SELECT語(yǔ)句

SELECT是關(guān)鍵字,每條SQL語(yǔ)句由一個(gè)或多個(gè)關(guān)鍵字構(gòu)成。

SELECT語(yǔ)句是最常用的SQL語(yǔ)句,用于從一個(gè)表或多個(gè)表中檢索數(shù)據(jù)。

為了能夠使用SELECT檢索數(shù)據(jù),需要至少兩個(gè)關(guān)鍵信息:選擇什么字段、從什么地方選擇。

4.2 檢索單個(gè)列

語(yǔ)法:

SELECT 字段名 FROM 表名;

注意,查詢出來(lái)的數(shù)據(jù)如果沒(méi)有明確排序查詢,那么返回的數(shù)據(jù)的順序沒(méi)有特殊意義,返回?cái)?shù)據(jù)的順序可能是數(shù)據(jù)被添加到表中的順序,也可能不是,只要返回相同數(shù)目的行,那么就是正確的。

結(jié)束SQL語(yǔ)句:多條SQL語(yǔ)句必須以分號(hào)分隔,單條SQL語(yǔ)句不一定需要加,但推薦加上。如果使用mysql命令行,必須加上分號(hào)。

SQL語(yǔ)句和大小寫(xiě):SQL語(yǔ)句不區(qū)分大小寫(xiě),如select和SELECT和Select效果是一樣的。

使用空格:在處理SQL語(yǔ)句時(shí),其中所有空格都會(huì)被忽略。SQL語(yǔ)句可以全部寫(xiě)在一行,也可以分多行書(shū)寫(xiě),但推薦分多行,便于調(diào)試和閱讀。

4.3 檢索多個(gè)列

語(yǔ)法:

SELECT 字段名,字段名,字段名... FROM 表名;

注意,多個(gè)列名之間通過(guò)逗號(hào)進(jìn)行分隔,但最后一個(gè)列名不加逗號(hào),否則發(fā)生錯(cuò)誤。

4.4 檢索所有列

語(yǔ)法:

SELECT * FROM 表名;

注意:給定一個(gè)通配符(*),則返回表中的所有列,列的順序一般是列在表中定義出現(xiàn)的順序。但如果添加或刪除列可能會(huì)導(dǎo)致順序變化。除此之外,還可以列出該表中所有列字段來(lái)達(dá)到檢索所有列的目的。

使用通配符:一般,除非你確實(shí)需要表中的每個(gè)列,否則最好別使用*通配符。雖然使用通配符可能會(huì)使你自己省事,不用明確列出所需列,但檢索不需要的列通常會(huì)降低檢索和應(yīng)用程序的性能。

檢索未知列:使用通配符有一個(gè)大優(yōu)點(diǎn)。由于不明確指定列名(因?yàn)樾翘?hào)檢索每個(gè)列),所以能檢索出名字未知的列。

4.5 檢索不同的行(去重)

語(yǔ)法:

SELECT DISTINCT 字段名 FROM 表名;

注意:使用distinct關(guān)鍵字,可以達(dá)到對(duì)字段去重的目的,但必須直接放在列名的前面。

不能部分使用DISTINCT:DISTINCT 關(guān)鍵字應(yīng)用于所有列而不僅是前置它的列。如果給出SELECT DISTINCT id,name則是根據(jù)id和name兩個(gè)字段去重的。如:

4.6 限制結(jié)果

所謂的限制結(jié)果,即使用LIMIT關(guān)鍵字來(lái)限定返回幾行。LIMIT 5表示返回前5行,LIMIT 5,5表示從行5開(kāi)始的5行返回。

語(yǔ)法如下:

LIMIT n; #返回前n行 LIMIT i,n; #將從行i(從0開(kāi)始)開(kāi)始的n行數(shù)據(jù)返回。第一個(gè)i表示開(kāi)始位置,第二個(gè)n表示要檢索的行數(shù)

行0:也就是說(shuō)LIMIT i,n中的i是從0開(kāi)始的,而不是從1開(kāi)始,就像Java中數(shù)組的索引也是從0開(kāi)始的而不是從1開(kāi)始的,LIMIT 1,1檢索出來(lái)的是第二行,LIMIT 0,1檢索出來(lái)的才是第一行。

在行數(shù)不夠時(shí):行數(shù)不夠時(shí),有多少行就返回多少行。

4.7 使用完全限定名

所謂的完全限定名就是同時(shí)使用表名和列名來(lái)鎖定某一列。

語(yǔ)法:

SELECT 表名.列名 FROM 表名; # 示例 select user.id,user.age from users;#返回user表中的id字段和age字段

注意:表名也可以使用完全限定名,即數(shù)據(jù)庫(kù)名.表名

第5章 排序檢索數(shù)據(jù)

5.1 排序數(shù)據(jù)

為什么要排序:檢索出的數(shù)據(jù)并不是以純粹的隨機(jī)順序出現(xiàn)的,如果不排序,則數(shù)據(jù)一般以在底層出現(xiàn)的順序顯示,可能是數(shù)據(jù)最初添加在表中的順序。但是,如果數(shù)據(jù)后來(lái)進(jìn)行過(guò)更新或刪除,則此順序?qū)?huì)受到MySQL重用回收存儲(chǔ)空間的影響。

子句(clause) SQL語(yǔ)句由子句構(gòu)成,有些子句是必需的,而有的是可選的。一個(gè)子句通常由一個(gè)關(guān)鍵字和所提供的數(shù)據(jù)組成。

排序使用ORDER BY子句,后面跟著一個(gè)或多個(gè)列名。語(yǔ)法:

SELECT 查詢列表 FROM 表名 ORDER BY 列名,列名,..

5.2 按多個(gè)列排序

經(jīng)常需要按多個(gè)字段進(jìn)行排序,比如姓名先按照姓排序,如果遇到相同的姓則按照名進(jìn)行排序。

為了按多個(gè)列排序,只要指定列名,列名之間用逗號(hào)分開(kāi)即可(就像選擇多個(gè)列時(shí)所做的那樣)。語(yǔ)法同上。

在按多個(gè)列排序時(shí),比如ORDER BY age,name,只有當(dāng)多個(gè)行具有相同的age值時(shí)才會(huì)對(duì)name進(jìn)行排序,如果age列中所有的值都是唯一的,那么則不會(huì)對(duì)name進(jìn)行排序。

5.3 指定排序方向

所謂的指定排序方向就是按照升序或降序。默認(rèn)是升序。降序需要指定DESC關(guān)鍵字。

語(yǔ)法:

# 單列指定排序方向 SELECT 查詢列表 FROM 表名 ORDER BY 字段名 [DESC|ASC] # 多列指定排序方向 SELECT 查詢列表 FROM 表名 ORDER BY 字段名 [DESC|ASC], 字段名 [DESC|ASC], ...

在多個(gè)列上降序排序 如果想在多個(gè)列上進(jìn)行降序排序,必須對(duì)每個(gè)列指定 DESC 關(guān)鍵字。

ASC關(guān)鍵字用于表示升序,但是默認(rèn)排序就是升序的;DESC表示降序,需要指定。

組合應(yīng)用:使用ORDER BY和LIMIT的組合,能夠找出一個(gè)列中最高或最低的值。

# 語(yǔ)法 SELECT 查詢列表 FROM 表名 ORDER BY 字段名 [DESC|ASC] LIMIT 1; # 示例 select prod_price from products order by prod_price desc limit;#找出最昂貴物品的值

ORDER BY 子句的位置 在給出 ORDER BY 子句時(shí),應(yīng)該保證它位于 FROM 子句之后。如果使用 LIMIT ,它必須位于 ORDER BY之后。使用子句的次序不對(duì)將產(chǎn)生錯(cuò)誤消息。

第6章 過(guò)濾數(shù)據(jù)

6.1 使用WHERE子句

在SELECT語(yǔ)句中,數(shù)據(jù)可以根據(jù)WHERE子句中指定的搜索條件進(jìn)行過(guò)濾。WHERE子句在表名(FROM子句)之后給出,語(yǔ)法如下:

SELECT 查詢條件 FROM 表名 WHERE 篩選條件

WHERE子句的位置:在同時(shí)使用 ORDER BY 和 WHERE 子句時(shí),應(yīng)該讓 ORDER BY 位于 WHERE 之后,否則將會(huì)產(chǎn)生錯(cuò)誤。

6.2 WHERE子句操作符

WHERE子句支持的操作符如下:

何時(shí)使用引號(hào):單引號(hào)用來(lái)限定字符串。如果將值與串類型(如varchar、char等)的列進(jìn)行比較,則需要限定引號(hào)。用來(lái)與數(shù)值列(int、float等)進(jìn)行比較的值不用引號(hào)。

注意:BETWEEN使用時(shí)必須指定兩個(gè)值,即所需范圍的低端值和高端值,比如age BETWEEN 18 AND 24,即年齡在18到24之間的所有記錄。?BETWEEN 匹配范圍中所有的值,包括指定的開(kāi)始值和結(jié)束值。

IS NULL子句:SELECT 語(yǔ)句有一個(gè)特殊的 WHERE 子句,可用來(lái)檢查具有 NULL 值的列。語(yǔ)法如下:

SELECT 查詢列表 FROM 表名 WHERE 字段名 IS NULL;#查詢某字段是否為NULL值的記錄 SELECT 查詢列表 FROM 表名 WHERE 字段名 IS NOT NULL;#查詢某字段是否不為NULL值的記錄

第7章 數(shù)據(jù)過(guò)濾

7.1 組合WHERE子句

即多條件過(guò)濾數(shù)據(jù),MySQL允許給出多個(gè)WHERE子句,這些子句有兩種使用方式:AND子句或OR子句。

7.1.1 AND操作符

表示不止一個(gè)條件進(jìn)行過(guò)濾,語(yǔ)法如下:

SELECT 查詢列表 FROM 表名 WHERE 篩選條件 AND 篩選條件 ....

必須同時(shí)滿足AND左右兩側(cè)的所有篩選條件。

7.1.2 OR操作符

OR操作符表示檢索匹配任一條件的行,即只要有一個(gè)條件成立就可以檢索需要的數(shù)據(jù)。

SELECT 查詢列表 FROM 表名 WHERE 篩選條件 OR 篩選條件 ....

只需要滿足OR左右兩側(cè)的任一條件。

7.1.3 計(jì)算次序

WHERE 可包含任意數(shù)目的 AND 和 OR 操作符。允許兩者結(jié)合以進(jìn)行復(fù)雜和高級(jí)的過(guò)濾。

引出問(wèn)題:同時(shí)存在AND和OR操作符時(shí),該如何查詢?

問(wèn)題原因:SQL(像多數(shù)語(yǔ)言一樣)在處理 OR 操作符前,優(yōu)先處理 AND 操作符。

解決問(wèn)題:此問(wèn)題的解決方法是使用圓括號(hào)明確地分組相應(yīng)的操作符。示例如下:

SELECT 查詢列表 FROM 表名 WHERE (篩選條件 OR 篩選條件) AND 篩選條件

因?yàn)閳A括號(hào)具有較 AND 或 OR 操作符高的計(jì)算次序,DBMS首先過(guò)濾圓括號(hào)內(nèi)的 OR 條件。

在WHERE子句中使用圓括號(hào):任何時(shí)候使用具有 AND 和 OR 操作符的 WHERE 子句,都應(yīng)該使用圓括號(hào)明確地分組操作符。不要過(guò)分依賴默認(rèn)計(jì)算次序,即使它確實(shí)是你想要的東西也是如此。使用圓括號(hào)沒(méi)有什么壞處,它能消除歧義。

7.2 IN操作符

圓括號(hào)在 WHERE 子句中還有另外一種用法。 IN 操作符用來(lái)指定條件范圍,范圍中的每個(gè)條件都可以進(jìn)行匹配。 IN 取合法值的由逗號(hào)分隔的清單,全都括在圓括號(hào)中。

SELECT 查詢列表 FROM 表名 WHERE 字段名 IN (值1,值2,...)

其實(shí)等價(jià)于OR操作符的功能:

SELECT 查詢列表 FROM 表名 WHERE 字段名=值1 OR 字段名=值2 OR ... # 注意,這里的字段名是同一個(gè)字段

為什么要使用 IN 操作符?其優(yōu)點(diǎn)具體如下。

  • 在使用長(zhǎng)的合法選項(xiàng)清單時(shí), IN 操作符的語(yǔ)法更清楚且更直觀。
  • 在使用 IN 時(shí),計(jì)算的次序更容易管理(因?yàn)槭褂玫牟僮鞣?#xff09;。
  • IN 操作符一般比 OR 操作符清單執(zhí)行更快。
  • IN 的最大優(yōu)點(diǎn)是可以包含其他 SELECT 語(yǔ)句,使得能夠更動(dòng)態(tài)地建立 WHERE 子句。

7.3 NOT操作符

WHERE 子句中的 NOT 操作符有且只有一個(gè)功能,那就是否定它之后所跟的任何條件。

例如:

# 查詢不在IN列表里的所有記錄 SELECT 查詢列表 FROM 表名 WHERE 字段名 NOT IN (值1,值2,...)

為什么使用 NOT ?對(duì)于簡(jiǎn)單的 WHERE 子句,使用 NOT 確實(shí)沒(méi)有什么優(yōu)勢(shì)。但在更復(fù)雜的子句中, NOT 是非常有用的。例如,在與 IN 操作符聯(lián)合使用時(shí), NOT 使找出與條件列表不匹配的行非常簡(jiǎn)單。

MySQL中的NOT :MySQL支持使用 NOT 對(duì) INBETWEENEXISTS子句取反,這與多數(shù)其他 DBMS允許使用 NOT 對(duì)各種條件取反有很大的差別。

  • NOT IN:表示不在IN列表中的所有記錄
  • NOT BETWEEN:表示不在某兩個(gè)值范圍之內(nèi)的所有記錄
  • NOT EXISTS:表示不存在某條件的記錄

第8章 用通配符進(jìn)行過(guò)濾

8.1 LIKE操作符

問(wèn)題提出:前面過(guò)濾數(shù)據(jù)的方法條件值都是已知的,如果要查找某字符串中包含"abc"的所有記錄,就需要用到通配符了。

通配符(wildcard) 用來(lái)匹配值的一部分的特殊字符。

搜索模式(search pattern)由字面值、通配符或兩者組合構(gòu)成的搜索條件。

通配符實(shí)際上是SQL的WHERE子句中具有特殊含義的字符。

為了能夠在搜索子句中使用通配符,必須使用LIKE操作符。

8.1.1 百分號(hào)(%)通配符

最常使用的通配符是百分號(hào)( % )。在搜索串中, % 表示任何字符出現(xiàn)任意次數(shù)

語(yǔ)法如下:

SELECT 查詢列表 FROM 表名 WHERE 字段名 LIKE '%關(guān)鍵字%';

區(qū)分大小寫(xiě) 根據(jù)MySQL的配置方式,搜索可以是區(qū)分大小寫(xiě)的。如果區(qū)分大小寫(xiě), 'jet%' 與 JetPack 1000 將不匹配。

通配符可在搜索模式中任意位置使用,并且可以使用多個(gè)通配符。

除了一個(gè)或多個(gè)字符外, % 還能匹配0個(gè)字符。 %代表搜索模式中給定位置的0個(gè)、1個(gè)或多個(gè)字符。

注意NULL 雖然似乎 % 通配符可以匹配任何東西,但有一個(gè)例外,即 NULL 。即使是 WHERE prod_name LIKE '%' 也不能匹配用值 NULL 作為產(chǎn)品名的行。

8.1.2 下劃線(_)通配符

另一個(gè)有用的通配符是下劃線( _ )。下劃線的用途與 % 一樣,但下劃線只匹配單個(gè)字符而不是多個(gè)字符

SELECT 查詢列表 FROM 表名 WHERE 字段名 LIKE '_關(guān)鍵字';

與 % 能匹配0個(gè)字符不一樣,_總是匹配一個(gè)字符,不能多也不能少。

8.2 使用通配符的技巧

使用通配符的技巧:

  • 不要過(guò)度使用通配符。如果其他操作符能達(dá)到相同的目的,應(yīng)該使用其他操作符。
  • 在確實(shí)需要使用通配符時(shí),除非絕對(duì)有必要,否則不要把它們用在搜索模式的開(kāi)始處(如'%關(guān)鍵字')。把通配符置于搜索模式的開(kāi)始處,搜索起來(lái)是最慢的。
  • 仔細(xì)注意通配符的位置。如果放錯(cuò)地方,可能不會(huì)返回想要的數(shù)據(jù)。

第9章 用正則表達(dá)式進(jìn)行搜索

9.1 正則表達(dá)式介紹

正則表達(dá)式是用來(lái)匹配文本的特殊的串(字符集合)。

  • 如果你想從一個(gè)文本文件中提取電話號(hào)碼,可以使用正則表達(dá)式。
  • 如果你需要查找名字中間有數(shù)字的所有文件,可以使用一個(gè)正則表達(dá)式。
  • 如果你想在一個(gè)文本塊中找到所有重復(fù)的單詞,可以使用一個(gè)正則表達(dá)式。
  • 如果你想替換一個(gè)頁(yè)面中的所有URL為這些URL的實(shí)際HTML鏈接,也可以使用一個(gè)正則表達(dá)式。

9.2 使用MySQL正則表達(dá)式

9.2.1 基本字符匹配

語(yǔ)法:

SELECT 查詢列表 FROM 表名 WHERE 字段名 REGEXP '正則表達(dá)式';

示例:

SELECT * from user WHERE username REGEXP '.三'; # 匹配username字段中所有第二個(gè)字符是'三'的記錄

?. 是正則表達(dá)式語(yǔ)言中一個(gè)特殊的字符。它表示匹配任意一個(gè)字符。

LIKE與REGEXP的區(qū)別:

SELECT * FROM user WHERE username LIKE '三';

SELECT * FROM user WHERE username REGEXP '三';

如果執(zhí)行上述兩條語(yǔ)句,會(huì)發(fā)現(xiàn)第一條語(yǔ)句不返回?cái)?shù)據(jù),而第二條語(yǔ)句返回所匹配的記錄。為什么?

?LIKE 匹配整個(gè)列。如果被匹配的文本在列值中出現(xiàn), LIKE 將不會(huì)找到它,相應(yīng)的行也不被返回(除非使用通配符)。而 REGEXP 在列值內(nèi)進(jìn)行匹配,如果被匹配的文本在列值中出現(xiàn), REGEXP 將會(huì)找到它,相應(yīng)的行將被返回。這是一個(gè)非常重要的差別。

匹配不區(qū)分大小寫(xiě) MySQL中的正則表達(dá)式匹配(自版本3.23.4后)不區(qū)分大小寫(xiě)(即,大寫(xiě)和小寫(xiě)都匹配)。為區(qū)分大小寫(xiě),可使用 BINARY 關(guān)鍵字,如 WHERE prod_name REGEXP BINARY 'JetPack .000' 。

9.2.2 進(jìn)行OR匹配

為搜索兩個(gè)串之一(或者為這個(gè)串,或者為另一個(gè)串),使用 |。語(yǔ)法如下:

SELECT 查詢列表 FROM 表名 WHERE 字段名 REGEXP '值1|值2|...';

示例:

SELECT * FROM user WHERE username REGEXP '三|四'; # 檢索username字段中待有'三'或'四'的記錄

使用 | 從功能上類似于在 SELECT 語(yǔ)句中使用 OR 語(yǔ)句,多個(gè) OR 條件可并入單個(gè)正則表達(dá)式。

兩個(gè)以上的 OR 條件 可以給出兩個(gè)以上的 OR 條件。例如,'1000 | 2000 | 3000' 將匹配 1000 或 2000 或 3000 。

9.2.3 匹配幾個(gè)字符之一

匹配任何單一字符。但是,如果你只想匹配特定的字符,怎么辦?可通過(guò)指定一組用 [ ] 括起來(lái)的字符來(lái)完成。

SELECT 查詢列表 FROM 表名 WHERE 字段名 REGEXP '[值1值2值3...]關(guān)鍵字';

示例:

SELECT * FROM user WHERE username REGEXP '[張李]三'; # 匹配username中第一個(gè)字符是'張'或'李',第二個(gè)字符是'三'的所有記錄 # 等價(jià)于 SELECT * FROM user WHERE username REGEXP '[張|李]三';

這里使用了正則表達(dá)式[張李]三。其中[張李]定義一組字符,它的意思是匹配'張'或'李',因?yàn)?#39;張三'和'李三'都匹配且返回,而且[ ]組中幾個(gè)值不需要用逗號(hào)進(jìn)行分隔開(kāi)。

正如所見(jiàn), [ ] 是另一種形式的 OR 語(yǔ)句。事實(shí)上,正則表達(dá)式 [123]Ton [1|2|3]Ton 的縮寫(xiě),也可以使用后者。

但如果使用REGEXP '1|2|3 Ton',那么匹配的是'1'或'2'或'3 Ton'。

因此除非把字符 | 括在一個(gè)集合中,否則它將應(yīng)用于整個(gè)串。

字符集合也可以被否定,即,它們將匹配除指定字符外的任何東西。為否定一個(gè)字符集,在集合的開(kāi)始處放置一個(gè) ^ 即可。因此,盡管 [123]匹配字符 1 、 2 或 3 ,但 [^123] 卻匹配除這些字符外的任何東西。

9.2.4 匹配范圍

集合可用來(lái)定義要匹配的一個(gè)或多個(gè)字符。例如,下面的集合將匹配數(shù)字0到9:[0123456789]

為簡(jiǎn)化這種類型的集合,可使用 - 來(lái)定義一個(gè)范圍。下面的式子功能上等同于上述數(shù)字列表:[0-9]

范圍不限于完整的集合, [1-3] [6-9] 也是合法的范圍。此外,范圍不一定只是數(shù)值的, [a-z] 匹配任意字母字符。

例如:

SELECT prod_name FROM products WHERE prod_name REGEXP '[1-5] Ton';

9.2.5 匹配特殊字符

如果要匹配如下這些特殊字符該怎么辦呢?

. [ ] | -

select * from user where username REGEXP '.';的語(yǔ)句是無(wú)效的。

為了匹配特殊字符,必須用 \\ 為前導(dǎo)。 \\- 表示查找 - , \\. 表示查找 . 。

select * from user where username REGEXP '\\.';這樣的語(yǔ)句才能查找成功。

這種處理就是所謂的轉(zhuǎn)義(escaping),正則表達(dá)式內(nèi)具有特殊意義的所有字符都必須以這種方式轉(zhuǎn)義。這包括 . 、 | 、 [] 以及迄今為止使用過(guò)的其他特殊字符。

\\也可以用來(lái)引用元字符(即具有特殊含義的字符)

匹配 \ 為了匹配反斜杠( \ )字符本身,需要使用 \\\\

\ 或 \\? 多數(shù)正則表達(dá)式實(shí)現(xiàn)使用單個(gè)反斜杠轉(zhuǎn)義特殊字符,以便能使用這些字符本身。但MySQL要求兩個(gè)反斜杠(MySQL自己解釋一個(gè),正則表達(dá)式庫(kù)解釋另一個(gè))。

9.2.6 匹配字符類

存在找出你自己經(jīng)常使用的數(shù)字、所有字母字符或所有數(shù)字字母字符等的匹配。為更方便工作,可以使用預(yù)定義的字符集,稱為字符類(character class)。

9.2.7 匹配多個(gè)實(shí)例

目前為止使用的所有正則表達(dá)式都試圖匹配單次出現(xiàn)。如果存在一個(gè)匹配,該行被檢索出來(lái),如果不存在,檢索不出任何行。但有時(shí)需要對(duì)匹配的數(shù)目進(jìn)行更強(qiáng)的控制。例如,你可能需要尋找所有的數(shù),不管數(shù)中包含多少數(shù)字,或者你可能想尋找一個(gè)單詞并且還能夠適應(yīng)一個(gè)尾隨的 s (如果存在),等等。

這可以用表9-3列出的正則表達(dá)式重復(fù)元字符來(lái)完成。

例如正則表達(dá)式 \\([0-9] sticks?\\) 需要解說(shuō)一下。 \\( 匹配 ),[0-9] 匹配任意數(shù)字(這個(gè)例子中為1和5), sticks? 匹配 stick和 sticks ( s 后的 ? 使 s 可選,因?yàn)?? 匹配它前面的任何字符的0次或1次出現(xiàn)), \\) 匹配 ) 。沒(méi)有 ? ,匹配 stick 和 sticks 會(huì)非常困難。

select * from user where username REGEXP '[[:digit:]]{4}';表示匹配連在一起的4個(gè)數(shù)字。如前所述, [:digit:] 匹配任意數(shù)字,因而它為數(shù)字的一個(gè)集合。 {4} 確切地要求它前面的字符(任意數(shù)字)出現(xiàn)4次,所以[[:digit:]]{4} 匹配連在一起的任意4位數(shù)字。

需要注意的是,在使用正則表達(dá)式時(shí),編寫(xiě)某個(gè)特殊的表達(dá)式幾乎總是有不止一種方法。上面的例子也可以如下編寫(xiě):REGEXP '[0-9][0-9][0-9][0-9]'。

9.2.8 定位符

目前為止的所有例子都是匹配一個(gè)串中任意位置的文本。為了匹配特定位置的文本,需要使用表9-4列出的定位符。

例如,如果你想找出以一個(gè)數(shù)(包括以小數(shù)點(diǎn)開(kāi)始的數(shù))開(kāi)始的所有產(chǎn)品,怎么辦?簡(jiǎn)單搜索 [0-9\\.] (或 [[:digit:]\\.] )不行,因?yàn)樗鼘⒃谖谋緝?nèi)任意位置查找匹配。解決辦法是使用 ^ 定位符,如下所示:REGEXP '^[0-9\\.]'。^ 匹配串的開(kāi)始。因此, ^[0-9\\.] 只在 . 或任意數(shù)字為串中第
一個(gè)字符時(shí)才匹配它們。

^ 的雙重用途 ^: 有兩種用法。在集合中(用 [ 和 ] 定義),用它來(lái)否定該集合,否則,用來(lái)指串的開(kāi)始處。

使 REGEXP 起類似 LIKE 的作用 : LIKE 和 REGEXP的不同在于, LIKE 匹配整個(gè)串而 REGEXP 匹配子串。利用定位符,通過(guò)用 ^ 開(kāi)始每個(gè)表達(dá)式,用 $ 結(jié)束每個(gè)表達(dá)式,可以使
REGEXP 的作用與 LIKE 一樣。

簡(jiǎn)單的正則表達(dá)式測(cè)試 可以在不使用數(shù)據(jù)庫(kù)表的情況下用SELECT 來(lái)測(cè)試正則表達(dá)式。 REGEXP 檢查總是返回 0 (沒(méi)有匹配)或 1 (匹配)。可以用帶文字串的 REGEXP 來(lái)測(cè)試表達(dá)式,并試
驗(yàn)它們。相應(yīng)的語(yǔ)法如下:SELECT 'hello' REGEXP '[0-9]';。這個(gè)例子顯然將返回 0 (因?yàn)槲谋?hello 中沒(méi)有數(shù)字)。

第10章 創(chuàng)建計(jì)算字段

10.1 計(jì)算字段

存儲(chǔ)在數(shù)據(jù)庫(kù)表中的數(shù)據(jù)一般不是應(yīng)用程序所需要的格式。下面舉幾個(gè)例子。

  • 如果想在一個(gè)字段中既顯示公司名,又顯示公司的地址,但這兩個(gè)信息一般包含在不同的表列中。
  • 城市、州和郵政編碼存儲(chǔ)在不同的列中(應(yīng)該這樣),但郵件標(biāo)簽打印程序卻需要把它們作為一個(gè)恰當(dāng)格式的字段檢索出來(lái)。
  • 列數(shù)據(jù)是大小寫(xiě)混合的,但報(bào)表程序需要把所有數(shù)據(jù)按大寫(xiě)表示出來(lái)。
  • 物品訂單表存儲(chǔ)物品的價(jià)格和數(shù)量,但不需要存儲(chǔ)每個(gè)物品的總價(jià)格(用價(jià)格乘以數(shù)量即可)。為打印發(fā)票,需要物品的總價(jià)格。
  • 需要根據(jù)表數(shù)據(jù)進(jìn)行總數(shù)、平均數(shù)計(jì)算或其他計(jì)算。

在上述每個(gè)例子中,存儲(chǔ)在表中的數(shù)據(jù)都不是應(yīng)用程序所需要的。我們需要直接從數(shù)據(jù)庫(kù)中檢索出轉(zhuǎn)換、計(jì)算或格式化過(guò)的數(shù)據(jù);而不是檢索出數(shù)據(jù),然后再在客戶機(jī)應(yīng)用程序或報(bào)告程序中重新格式化。

計(jì)算字段并不實(shí)際存在于數(shù)據(jù)庫(kù)表中。計(jì)算字段是運(yùn)行時(shí)在 SELECT 語(yǔ)句內(nèi)創(chuàng)建的。

字段(field): 基本上與列(column)的意思相同,經(jīng)常互換使用,不過(guò)數(shù)據(jù)庫(kù)列一般稱為列,而術(shù)語(yǔ)字段通常用在計(jì)算字段的連接上。

10.2 拼接字段

拼接(concatenate) 將值聯(lián)結(jié)到一起構(gòu)成單個(gè)值。比如姓和名連接到一起就是姓名。

在MySQL的 SELECT 語(yǔ)句中,可使用Concat() 函數(shù)來(lái)拼接兩個(gè)列。

MySQL的不同之處 多數(shù)DBMS使用 + 或 || 來(lái)實(shí)現(xiàn)拼接,MySQL則使用 Concat() 函數(shù)來(lái)實(shí)現(xiàn)。當(dāng)把SQL語(yǔ)句轉(zhuǎn)換成MySQL語(yǔ)句時(shí)一定要把這個(gè)區(qū)別銘記在心。

SELECT CONCAT(字段或字符串, 字段或字符串, ...) FROM 表名 WHERE 篩選條件;

Trim 函數(shù) MySQL除了支持 RTrim() (正如剛才所見(jiàn),它去掉串右邊的空格),還支持 LTrim() (去掉串左邊的空格)以及Trim() (去掉串左右兩邊的空格)。

別名(alias)是一個(gè)字段或值的替換名。別名用 AS 關(guān)鍵字賦予。

SELECT 字段名 AS 別名 FROM 表名;

別名的其他用途 別名還有其他用途。常見(jiàn)的用途包括在實(shí)際的表列名包含不符合規(guī)定的字符(如空格)時(shí)重新命名它,在原來(lái)的名字含混或容易誤解時(shí)擴(kuò)充它,等等。

導(dǎo)出列 別名有時(shí)也稱為導(dǎo)出列(derived column),不管稱為什么,它們所代表的都是相同的東西。

10.3 執(zhí)行算術(shù)運(yùn)算

計(jì)算字段的另一常見(jiàn)用途是對(duì)檢索出的數(shù)據(jù)進(jìn)行算術(shù)計(jì)算。如加減乘除等。

MySQL支持表10-1中列出的基本算術(shù)操作符。此外,圓括號(hào)可用來(lái)區(qū)分優(yōu)先順序。

如何測(cè)試計(jì)算 SELECT :提供了測(cè)試和試驗(yàn)函數(shù)與計(jì)算的一個(gè)很好的辦法。雖然 SELECT 通常用來(lái)從表中檢索數(shù)據(jù),但可以省略 FROM 子句以便簡(jiǎn)單地訪問(wèn)和處理表達(dá)式。例如, SELECT 3*2; 將返回 6 , SELECT Trim('abc'); 將返回 abc ,而 SELECT Now() 利用 Now() 函數(shù)返回當(dāng)前日期和時(shí)間。通過(guò)這些例子,可以明白如何根據(jù)需要使用 SELECT 進(jìn)行試驗(yàn)。

第11章 使用數(shù)據(jù)處理函數(shù)

11.1 函數(shù)

如TRIM()函數(shù)去除空格。

函數(shù)沒(méi)有SQL的可移植性強(qiáng) 因?yàn)椴煌腄BMS支持其他DBMS不支持的函數(shù),有時(shí)差異還很大,所以移植性差。

11.2 使用函數(shù)

大多數(shù)SQL實(shí)現(xiàn)支持以下類型的函數(shù):

  • 用于處理文本串(如刪除或填充值,轉(zhuǎn)換值為大寫(xiě)或小寫(xiě))的文本函數(shù)。
  • ?用于在數(shù)值數(shù)據(jù)上進(jìn)行算術(shù)操作(如返回絕對(duì)值,進(jìn)行代數(shù)運(yùn)算)的數(shù)值函數(shù)。
  • 用于處理日期和時(shí)間值并從這些值中提取特定成分(例如,返回兩個(gè)日期之差,檢查日期有效性等)的日期和時(shí)間函數(shù)。
  • 返回DBMS正使用的特殊信息(如返回用戶登錄信息,檢查版本細(xì)節(jié))的系統(tǒng)函數(shù)。

11.2.1 文本處理函數(shù)

?SOUNDEX 是一個(gè)將任何文本串轉(zhuǎn)換為描述其語(yǔ)音表示的字母數(shù)字模式的算法。 SOUNDEX 考慮了類似的發(fā)音字符和音節(jié),使得能對(duì)串進(jìn)行發(fā)音比較而不是字母比較。雖然SOUNDEX 不是SQL概念,但MySQL(就像多數(shù)DBMS一樣)都提供對(duì)SOUNDEX 的支持。如下:

11.2.2 日期和時(shí)間處理函數(shù)

應(yīng)該總是使用4位數(shù)字的年份 支持2位數(shù)字的年份,MySQL處理00-69為2000-2069,處理70-99為1970-1999。雖然它們可能是打算要的年份,但使用完整的4位數(shù)字年份更可靠,因?yàn)镸ySQL不必做出任何假定。

11.2.3 數(shù)值處理函數(shù)

數(shù)值處理函數(shù)僅處理數(shù)值數(shù)據(jù)。這些函數(shù)一般主要用于代數(shù)、三角或幾何運(yùn)算,因此沒(méi)有串或日期 — 時(shí)間處理函數(shù)的使用那么頻繁。

第12章 匯總數(shù)據(jù)

12.1 聚集函數(shù)

我們經(jīng)常需要匯總數(shù)據(jù)而不用把它們實(shí)際檢索出來(lái),為此MySQL提供了專門(mén)的函數(shù)。使用這些函數(shù),MySQL查詢可用于檢索數(shù)據(jù),以便分析和報(bào)表生成。這種類型的檢索例子有以下幾種。

  • 確定表中行數(shù)(或者滿足某個(gè)條件或包含某個(gè)特定值的行數(shù))。
  • 獲得表中行組的和。
  • 找出表列(或所有行或某些特定的行)的最大值、最小值和平均值。

聚集函數(shù)(aggregate function) 運(yùn)行在行組上,計(jì)算和返回單個(gè)值的函數(shù)。

12.1.1 AVG()函數(shù)

AVG() 通過(guò)對(duì)表中行數(shù)計(jì)數(shù)并計(jì)算特定列值之和,求得該列的平均值。 AVG() 可用來(lái)返回所有列的平均值,也可以用來(lái)返回特定列或行的平均值。

SELECT AVG(列名) FROM 表名 WHERE 篩選條件; # 例如:select AVG(price) from products where id=100;

只用于單個(gè)列 AVG()只能用來(lái)確定特定數(shù)值列的平均值,而且列名必須作為函數(shù)參數(shù)給出。為了獲得多個(gè)列的平均值,必須使用多個(gè) AVG() 函數(shù)。

NULL值 AVG() 函數(shù)忽略列值為 NULL 的行。

12.1.2 COUNT()函數(shù)

COUNT() 函數(shù)進(jìn)行計(jì)數(shù)。可利用 COUNT() 確定表中行的數(shù)目或符合特定條件的行的數(shù)目。COUNT() 函數(shù)有兩種使用方式。

  • 使用 COUNT(*) 對(duì)表中行的數(shù)目進(jìn)行計(jì)數(shù),不管表列中包含的是空值( NULL )還是非空值。
  • 使用 COUNT(column) 對(duì)特定列中具有值的行進(jìn)行計(jì)數(shù),忽略NULL 值。

NULL 值 如果指定列名,則指定列的值為空的行被 COUNT()函數(shù)忽略,但如果 COUNT() 函數(shù)中用的是星號(hào)( * ),則不忽略。

12.1.3 MAX()函數(shù)

MAX() 返回指定列中的最大值。 MAX() 要求指定列名。

對(duì)非數(shù)值數(shù)據(jù)使用 MAX() 雖然 MAX() 一般用來(lái)找出最大的數(shù)值或日期值,但MySQL允許將它用來(lái)返回任意列中的最大值,包括返回文本列中的最大值。在用于文本數(shù)據(jù)時(shí),如果數(shù)據(jù)按相應(yīng)的列排序,則 MAX() 返回最后一行。

NULL值 MAX() 函數(shù)忽略列值為 NULL 的行。

12.1.4 MIN()函數(shù)?

MIN() 的功能正好與 MAX() 功能相反,它返回指定列的最小值。與MAX() 一樣, MIN() 要求指定列名。

對(duì)非數(shù)值數(shù)據(jù)使用MIN() MIN()函數(shù)與 MAX() 函數(shù)類似,MySQL允許將它用來(lái)返回任意列中的最小值,包括返回文本列中的最小值。在用于文本數(shù)據(jù)時(shí),如果數(shù)據(jù)按相應(yīng)的列排序,則 MIN() 返回最前面的行。

NULL值 MIN() 函數(shù)忽略列值為 NULL 的行。

12.1.5 SUM()函數(shù)

SUM() 用來(lái)返回指定列值的和(總計(jì))。SUM() 也可以用來(lái)合計(jì)計(jì)算值。

在多個(gè)列上進(jìn)行計(jì)算 利用標(biāo)準(zhǔn)的算術(shù)操作符,所有聚集函數(shù)都可用來(lái)執(zhí)行多個(gè)列上的計(jì)算。

NULL 值 SUM() 函數(shù)忽略列值為 NULL 的行。

12.2 聚集不同值

以上5個(gè)聚集函數(shù)都可以如下使用:

  • 對(duì)所有的行執(zhí)行計(jì)算,指定 ALL 參數(shù)或不給參數(shù)(因?yàn)?ALL 是默認(rèn)行為);
  • 只包含不同的值,指定 DISTINCT 參數(shù)。

ALL 為默認(rèn) ALL 參數(shù)不需要指定,因?yàn)樗悄J(rèn)行為。如果不指定 DISTINCT ,則假定為 ALL 。

SELECT 聚集函數(shù)(DISTINCT 列名) FROM 表名 WHERE 篩選條件; # 例如:select avg(distinct price) from products;

注意 如果指定列名,則 DISTINCT 只能用于 COUNT() 。 DISTINCT不能用于 COUNT(*),因此不允許使用COUNT(DISTINCT),否則會(huì)產(chǎn)生錯(cuò)誤 。類似地, DISTINCT 必須使用列名,不能用于計(jì)算或表達(dá)式。

將 DISTINCT 用于 MIN() 和 MAX() 雖然 DISTINCT 從技術(shù)上可用于 MIN() 和 MAX() ,但這樣做實(shí)際上沒(méi)有價(jià)值。一個(gè)列中的最小值和最大值不管是否包含不同值都是相同的。

12.3 組合聚集函數(shù)

實(shí)際上 SELECT語(yǔ)句可根據(jù)需要包含多個(gè)聚集函數(shù)。例如:

SELECT COUNT(*) AS num_items,MIN(price) AS price_min,MAX(price) AS price_max,AVG(price) AS price_avg FROM products;

取別名 在指定別名以包含某個(gè)聚集函數(shù)的結(jié)果時(shí),不應(yīng)該使用表中實(shí)際的列名。雖然這樣做并非不合法,但使用唯一的名字會(huì)使你的SQL更易于理解和使用(以及將來(lái)容易排除故障)。

第13章 分組數(shù)據(jù)

13.1 分組

例如要計(jì)算每個(gè)班的總分,就需要按班分組了。

分組允許把數(shù)據(jù)分為多個(gè)邏輯組,以便能對(duì)每個(gè)組進(jìn)行聚集計(jì)算。

13.2 創(chuàng)建分組

分組是在 SELECT 語(yǔ)句的 GROUP BY 子句中建立的。例如:

SELECT SUM(score) FROM classes GROUP BY class_id;# 計(jì)算每個(gè)班的總分

在具體使用 GROUP BY 子句前,需要知道一些重要的規(guī)定:

  • GROUP BY 子句可以包含任意數(shù)目的列。這使得能對(duì)分組進(jìn)行嵌套,為數(shù)據(jù)分組提供更細(xì)致的控制。
  • 如果在 GROUP BY 子句中嵌套了分組,數(shù)據(jù)將在最后規(guī)定的分組上進(jìn)行匯總。換句話說(shuō),在建立分組時(shí),指定的所有列都一起計(jì)算(所以不能從個(gè)別的列取回?cái)?shù)據(jù))。
  • GROUP BY 子句中列出的每個(gè)列都必須是檢索列或有效的表達(dá)式(但不能是聚集函數(shù))。如果在 SELECT 中使用表達(dá)式,則必須在GROUP BY 子句中指定相同的表達(dá)式。不能使用別名。
  • 除聚集計(jì)算語(yǔ)句外, SELECT 語(yǔ)句中的每個(gè)列都必須在 GROUP BY 子句中給出。
  • 如果分組列中具有 NULL 值,則 NULL 將作為一個(gè)分組返回。如果列中有多行 NULL 值,它們將分為一組。
  • GROUP BY 子句必須出現(xiàn)在 WHERE 子句之后, ORDER BY 子句之前。

使用 ROLLUP 使用 WITH ROLLUP 關(guān)鍵字,可以得到每個(gè)分組以及每個(gè)分組匯總級(jí)別(針對(duì)每個(gè)分組)的值,如下所示:

13.3 過(guò)濾分組

除了能用 GROUP BY 分組數(shù)據(jù)外,MySQL還允許過(guò)濾分組,規(guī)定包括哪些分組,排除哪些分組。

比如列出總分在100以上的班級(jí)。

?WHERE 過(guò)濾指定的是行而不是分組。事實(shí)上, WHERE 沒(méi)有分組的概念。

MySQL為此目的提供了另外的子句,那就是 HAVING 子句。 HAVING 非常類似于 WHERE 。事實(shí)上,目前為止所學(xué)過(guò)的所有類型的 WHERE 子句都可以用 HAVING 來(lái)替代。唯一的差別是WHERE 過(guò)濾行,而 HAVING 過(guò)濾分組。

總結(jié):WHERE是分組前篩選;HAVING是分組后篩選。

HAVING 支持所有 WHERE 操作符 所學(xué)過(guò)的有關(guān) WHERE 的所有這些技術(shù)和選項(xiàng)都適用于HAVING 。它們的句法是相同的,只是關(guān)鍵字有差別。

例如:

select sum(score),class_id from user group by class_id having sum(score)>100; # 查看總分在100以上的班級(jí)

HAVING 和 WHERE 的差別 這里有另一種理解方法, WHERE 在數(shù)據(jù)分組前進(jìn)行過(guò)濾, HAVING 在數(shù)據(jù)分組后進(jìn)行過(guò)濾。這是一個(gè)重要的區(qū)別, WHERE 排除的行不包括在分組中。這可能會(huì)改變計(jì)算值,從而影響 HAVING 子句中基于這些值過(guò)濾掉的分組。

注意是可以同時(shí)使用WHERE和HAVING語(yǔ)句的。

SELECT 查詢列表,聚合函數(shù) FROM 表名 WHERE 篩選條件 GROUP BY 分組字段 HAVING 分組后的篩選條件;

13.4 分組和排序

雖然 GROUP BY 和 ORDER BY 經(jīng)常完成相同的工作,但它們是非常不同的。表13-1匯總了它們之間的差別。

不要忘記 ORDER BY 一般在使用 GROUP BY 子句時(shí),應(yīng)該也給出 ORDER BY 子句。這是保證數(shù)據(jù)正確排序的唯一方法。千萬(wàn)不要僅依賴 GROUP BY 排序數(shù)據(jù)。

SELECT 查詢列表,聚合函數(shù) FROM 表名 GROUP BY 分組字段 HAVING 分組后的篩選條件 ORDER BY 排序字段;

13.5 SELECT子句順序

表13-2以在 SELECT 語(yǔ)句中使用時(shí)必須遵循的次序,列出迄今為止所學(xué)過(guò)的子句。

例如:

SELECT 查詢列表,聚合函數(shù) FROM 表名 WHERE 分組前的篩選條件 GROUP BY 分組字段 HAVING 分組后的篩選條件 ORDER BY 排序字段 LIMIT 起始索引,顯示條數(shù);

第14章 使用子查詢

14.1 子查詢

SQL還允許創(chuàng)建子查詢(subquery),即嵌套在其他查詢中的查詢。

14.2 利用子查詢進(jìn)行過(guò)濾

例如:

可見(jiàn),在 WHERE 子句中使用子查詢能夠編寫(xiě)出功能很強(qiáng)并且很靈活的SQL語(yǔ)句。對(duì)于能嵌套的子查詢的數(shù)目沒(méi)有限制,不過(guò)在實(shí)際使用時(shí)由于性能的限制,不能嵌套太多的子查詢。

雖然子查詢一般與 IN 操作符結(jié)合使用,但也可以用于測(cè)試等于( = )、不等于( <> )等。

14.3 作為計(jì)算字段使用子查詢

使用子查詢的另一方法是創(chuàng)建計(jì)算字段。即使用聚合函數(shù)如COUNT等。

注意,這個(gè)子查詢是在SELECT后面的,即是查詢列表的一部分,而且使用到了WHERE orders.cust_id=customers.cust_id,這種涉及到外部查詢的子查詢。

相關(guān)子查詢(correlated subquery) 涉及外部查詢的子查詢。這種類型的子查詢稱為相關(guān)子查詢。任何時(shí)候只要列名可能有多義性,就必須使用這種語(yǔ)法(表名和列名由一個(gè)句點(diǎn)分隔)。如果不使用完全限定列名則查詢失敗:

逐漸增加子查詢來(lái)建立查詢 用子查詢測(cè)試和調(diào)試查詢很有技巧性,特別是在這些語(yǔ)句的復(fù)雜性不斷增加的情況下更是如此。用子查詢建立(和測(cè)試)查詢的最可靠的方法是逐漸進(jìn)行,這與MySQL處理它們的方法非常相同。首先,建立和測(cè)試最內(nèi)層的查詢。然后,用硬編碼數(shù)據(jù)建立和測(cè)試外層查詢,并且僅在確認(rèn)它正常后才嵌入子查詢。這時(shí),再次測(cè)試它。對(duì)于要增加的每個(gè)查詢,重復(fù)這些步驟。這樣做僅給構(gòu)造查詢?cè)黾恿艘稽c(diǎn)點(diǎn)時(shí)間,但節(jié)省了以后(找出查詢?yōu)槭裁床徽?#xff09;的大量時(shí)間,并且極大地提高了查詢一開(kāi)始就正常工作的可能性。

第15章 聯(lián)結(jié)表

15.1 聯(lián)結(jié)

SQL最強(qiáng)大的功能之一就是能在數(shù)據(jù)檢索查詢的執(zhí)行中聯(lián)結(jié)(join)表。

所謂的聯(lián)結(jié)就是多表查詢

15.1.1 關(guān)系表

例如產(chǎn)品信息和供應(yīng)商信息,應(yīng)該用兩張表來(lái)存儲(chǔ),而不是一張表。關(guān)系表的設(shè)計(jì)就是要保證把信息分解成多個(gè)表,一類數(shù)據(jù)一個(gè)表。各表通過(guò)某些常用的值(即關(guān)系設(shè)計(jì)中的關(guān)系(relational))互相關(guān)聯(lián)。

外鍵(foreign key) 外鍵為某個(gè)表中的一列,它包含另一個(gè)表的主鍵值,定義了兩個(gè)表之間的關(guān)系。

關(guān)系數(shù)據(jù)庫(kù)的可伸縮性遠(yuǎn)比非關(guān)系數(shù)據(jù)庫(kù)要好。

可伸縮性(scale) 能夠適應(yīng)不斷增加的工作量而不失敗。設(shè)計(jì)良好的數(shù)據(jù)庫(kù)或應(yīng)用程序稱之為可伸縮性好(scale well)。

15.1.2 為什么要使用聯(lián)結(jié)

如果數(shù)據(jù)存儲(chǔ)在多個(gè)表中,怎樣用單條 SELECT 語(yǔ)句檢索出數(shù)據(jù)?
答案是使用聯(lián)結(jié)。簡(jiǎn)單地說(shuō),聯(lián)結(jié)是一種機(jī)制,用來(lái)在一條 SELECT語(yǔ)句中關(guān)聯(lián)表,因此稱之為聯(lián)結(jié)。使用特殊的語(yǔ)法,可以聯(lián)結(jié)多個(gè)表返回一組輸出,聯(lián)結(jié)在運(yùn)行時(shí)關(guān)聯(lián)表中正確的行。

總結(jié):為了能夠使用一條SQL語(yǔ)句完成多張表的查詢。

15.2 創(chuàng)建聯(lián)結(jié)

語(yǔ)法如下:

SELECT 查詢列表 FROM 表1,表2 WHERE 聯(lián)結(jié)條件;

例如:

完全限定列名 在引用的列可能出現(xiàn)二義性時(shí),必須使用完全限定列名(用一個(gè)點(diǎn)分隔的表名和列名)。如果引用一個(gè)沒(méi)有用表名限制的具有二義性的列名,MySQL將返回錯(cuò)誤。

15.2.1 WHERE子句的重要性

利用 WHERE 子句建立聯(lián)結(jié)關(guān)系似乎有點(diǎn)奇怪,但實(shí)際上,有一個(gè)很充分的理由。請(qǐng)記住,在一條 SELECT 語(yǔ)句中聯(lián)結(jié)幾個(gè)表時(shí),相應(yīng)的關(guān)系是在運(yùn)行中構(gòu)造的。在數(shù)據(jù)庫(kù)表的定義中不存在能指示MySQL如何對(duì)表進(jìn)行聯(lián)結(jié)的東西。你必須自己做這件事情。在聯(lián)結(jié)兩個(gè)表時(shí),你實(shí)際上做的是將第一個(gè)表中的每一行與第二個(gè)表中的每一行配對(duì)。 WHERE 子句作為過(guò)濾條件,它只包含那些匹配給定條件(這里是聯(lián)結(jié)條件)的行。沒(méi)有WHERE 子句,第一個(gè)表中的每個(gè)行將與第二個(gè)表中的每個(gè)行配對(duì),而不管它們邏輯上是否可以配在一起。

總之,WHERE子句是為了阻止笛卡兒積結(jié)果的產(chǎn)生,即不能讓第一個(gè)表的每一行匹配第二個(gè)表的所有行。

笛卡兒積(cartesian product) 由沒(méi)有聯(lián)結(jié)條件的表關(guān)系返回的結(jié)果為笛卡兒積。檢索出的行的數(shù)目將是第一個(gè)表中的行數(shù)乘以第二個(gè)表中的行數(shù)。

不要忘了 WHERE 子句 應(yīng)該保證所有聯(lián)結(jié)都有 WHERE 子句,否則MySQL將返回比想要的數(shù)據(jù)多得多的數(shù)據(jù)。同理,應(yīng)該保證 WHERE 子句的正確性。不正確的過(guò)濾條件將導(dǎo)致MySQL返回不正確的數(shù)據(jù)。

15.2.2 內(nèi)部聯(lián)結(jié)

目前為止所用的聯(lián)結(jié)稱為等值聯(lián)結(jié)(equijoin),它基于兩個(gè)表之間的相等測(cè)試。這種聯(lián)結(jié)也稱為內(nèi)部聯(lián)結(jié)。其實(shí),對(duì)于這種聯(lián)結(jié)可以使用稍微不同的語(yǔ)法來(lái)明確指定聯(lián)結(jié)的類型。如下語(yǔ)法:

SELECT 查詢列表 FROM 表1 INNER JOIN 表2 ON 聯(lián)結(jié)條件;

使用哪種語(yǔ)法 ANSI SQL規(guī)范首選 INNER JOIN 語(yǔ)法。此外,盡管使用 WHERE 子句定義聯(lián)結(jié)的確比較簡(jiǎn)單,但是使用明確的聯(lián)結(jié)語(yǔ)法能夠確保不會(huì)忘記聯(lián)結(jié)條件,有時(shí)候這樣做也能影響性能。推薦使用INNER JOIN...ON...

15.2.3 聯(lián)結(jié)多個(gè)表

SQL對(duì)一條 SELECT 語(yǔ)句中可以聯(lián)結(jié)的表的數(shù)目沒(méi)有限制。創(chuàng)建聯(lián)結(jié)的基本規(guī)則也相同。首先列出所有表,然后定義表之間的關(guān)系。

SELECT 查詢列表 FROM 表1,表2,表3,.. WHERE 聯(lián)結(jié)條件1 AND 聯(lián)結(jié)條件2 AND ...

性能考慮 MySQL在運(yùn)行時(shí)關(guān)聯(lián)指定的每個(gè)表以處理聯(lián)結(jié)。這種處理可能是非常耗費(fèi)資源的,因此應(yīng)該仔細(xì),不要聯(lián)結(jié)不必要的表。聯(lián)結(jié)的表越多,性能下降越厲害。

多做實(shí)驗(yàn) 正如所見(jiàn),為執(zhí)行任一給定的SQL操作,一般存在不止一種方法。很少有絕對(duì)正確或絕對(duì)錯(cuò)誤的方法。性能可能會(huì)受操作類型、表中數(shù)據(jù)量、是否存在索引或鍵以及其他一些條件的影響。因此,有必要對(duì)不同的選擇機(jī)制進(jìn)行實(shí)驗(yàn),以找出最適合具體情況的方法。

總結(jié)

以上是生活随笔為你收集整理的《SQL必知必会》读书笔记上(第1~15章)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。