SQL語言是一門簡單易學卻又功能強大的語言,他讓你快速上手並寫出比較複雜的查詢語句,但對於大多數開發者來書,使用SQL查詢數據庫並無一個抽象的過程和一個合理的步驟,這極可能會是在寫一些特定的查詢語句來解決特定問題是被卡住。本系列文章主要講述SQL查詢時一些基本的理論,以及寫查詢語句的抽象思路。html
這是轉自http://www.cnblogs.com/CareySon/archive/2010/04/05/1704928.html的一篇文章。算法
但願在看文章的同時我也看以對SQL查詢有更多的瞭解和學習。sql
SQL查詢簡介:數據庫
SQL語言起源於1970年E.J.Codd發表的關係數據庫理論,因此SQL是爲關係數據庫服務的。數據庫設計
而對於SQL查詢,是指從數據庫中取得數據的子集。函數
精確查詢的前置條件:性能
對於正確取得所須要的數據子集,除了須要思路正確並將思路正確轉變爲對應的SQL查詢語句以外,還有很重要的一點是須要數據庫有良好的設計,這裏的良好設計我所指的是數據庫設計符合業務邏輯並至少實現第三範式。對於實現第三範式,這只是我的觀點。學習
兩種方式,同一結果:優化
在SQL中,取得相同的數據子集能夠用不一樣的思路或不一樣的SQL語句,由於SQL源於關係數據庫理論,而關係數據庫理論又源於數學,思考如何構建查詢語句時,均可以抽象爲兩種方法:加密
一、關係代數法,關係代數法的思路是對數據庫進行分佈操做,最後取得想要的結果。
好比:
Select Name,Department,Age
From Employee
where Age>20
關係代數的思路描述上面的語句爲:對標Employee表進行投影(選擇列)操做,而後對結果進行篩選,只取得年齡大於20 的結果。
二、關係演算法,相比較於關係代數而言,關係演算法更多的是取得數據所知足的條件,上面SQL能夠用關係演算法描述爲u:我想獲得全部年齡大於20歲的員工的姓名、部門和年齡。
爲何須要兩種方法
對於簡單的查詢語句來講,上面兩種方法都不須要.用腳就能夠想出來了。問題在於不少查詢語句都會很是複雜。對於關係演算法來講更多的是關注的是所取出信息所知足的條件,而對於關係代數法來講,更多關注的是如何取出特定的信息.簡單的說,關係演算法表示的是」what」,而關係代數法表達的是」how」.SQL語句中所透漏的思路,有些時候是關係代數法,有些時候是關係演算法,還有些是兩種思路的混合.
對於某些查詢狀況,關係代數法可能會更簡單,而對於另一些狀況,關係演算法則會顯得更直接.還有一些狀況.咱們須要混合兩種思路。因此這兩種思惟方式在寫SQL查詢時都是必須的.
單表查詢:
單表查詢是全部查詢的中間狀態,既是多個表的複雜查詢在最終進行這種鏈接後都可以被抽象成單表查詢,因此最早從單表查詢開始:
根據上面數據子集的說法,選擇列是經過在select語句後面添加所要選擇的列名實現的:
好比下面數據庫中經過在select後面選擇相應的列名實現選擇列的子集.
相應sql語句以下:
選擇行的子集是在Sql語句的where子句後面加上相應的限制條件,當where子句後面的表達式爲「真」時,也就是知足所謂的「條件」時,相應的行的子集被返回。
where子句後面的運算符分爲兩類,分別是比較運算符和邏輯運算符.
比較運算符是將兩個相同類型的數據進行比較,進而返回布爾類型(bool)的運算符,在SQL中,比較運算符一共有六種,分別爲等於(=),小於(<),大於(>),小於或等於(<=),大於或等於(>=)以及不等於(<>),其中小於或等於和大於或等於能夠當作是比較運算符和邏輯運算符的結合體。
而邏輯運算符是將兩個布爾類型進行鏈接,並返回一個新的布爾類型的運算符,在SQL中,邏輯運算符一般是將比較運算符返回的布爾類型相鏈接以最終肯定where子句後面知足條件的真假。邏輯運算符一種有三種,與(AND),或(OR),非(NOT).
好比上面,我想選擇第二條和第六條,爲了說明比較運算符和邏輯運算符,可使用以下Sql語句:
SELECT [Name] ,[GroupName] FROM [AdventureWorks].[HumanResources].[Department] WHERE DepartmentID>1 and DepartmentID<3 or DepartmentID>5 and DepartmentID<7
由此咱們能夠看出,這幾種運算符是有優先級的,優先級由大到小排列是比較運算符>於(And)>非(Or)
固然,運算符也能夠經過小括號來改變優先級,對於上面那個表
對於不加括號時:
SELECT * FROM [AdventureWorks].[HumanResources].[Department] WHERE DepartmentID>=1 and DepartmentID<=3 and DepartmentID>=5 or DepartmentID<=7
加了括號改變運算順序後:
SELECT * FROM [AdventureWorks].[HumanResources].[Department] WHERE DepartmentID>=1 and DepartmentID<=3 and (DepartmentID>=5 or DepartmentID<=7)
假如在一個用戶註冊的表中,一些選填信息並不須要用戶必須填寫,則在數據庫中保存爲null,這些null值在利用上面where子句後的運算符時,有可能形成數據丟失,好比一個選填信息是性別(Gender),假設下面兩條條件子句:
where Gender="M"
因爲null值的存在,這兩條語句返回的數據行加起來並非整個表中的全部數據。因此,當將null值考慮在內時,where後面的條件子句擁有可能的值從真和假,增長爲真,假,以及未知(null)。這些是咱們在現實世界中想一些問題的時候可能的答案--真的,假的,我不知道。
因此咱們如何在這種狀況下不丟失數據呢,對於上面的例子來講,如何才能讓整個表的數據不被丟失呢,這裏必須將除了「真」,「假」之外的「未知」這個選項包含在內,SQL提供了IS NULL來代表未知這個選項:
將上面語句加入進去,則不會再丟失數據。
上面的那些方法都是關於取出數據,而下面是關於將取出的子集進行排序。SQL經過Order by子句來進行排序,Order by子句是Sql查詢語句的最後一個子句,也就是說Order by子句以後不能再加任何的子句了。
Order By子句分爲升序(ASC)和降序(DESC),若是不指定升序或者降序,則默認爲升序(由小到大),而Order by是根據排序依據的數據類型決定,分別爲3種數據類型能夠進行排序:
字符按照字母表進行排序,數字根據數字大小排序,時間日期根據時間的前後進行排序。
視圖能夠看做是一個保存的虛擬表,也能夠簡單看作是保存的一個查詢語句。視圖的好處是視圖能夠根據視圖所查詢表的內容的改變而改變,打個比方來理解這句話是:
使用視圖的優勢是能夠對查詢進行加密以及便於管理,聽說還能夠優化性能(我不承認這點).
有時候咱們對於取出的數據子集不想重複,好比你想知道一些特定的員工一共屬於幾個部門
SELECT [EmployeeID] ,[DepartmentID] FROM [AdventureWorks].[HumanResources].[EmployeeDepartmentHistory]
這樣的結果是沒有意義的,SQL提供了Distinct關鍵字來實現這點:
所謂聚合函數,是爲了一些特定目的,將同一列多個值聚合爲一個,好比我想知道一羣人中最大年齡是多少能夠利用MAX(Age),好比我想知道一個班級平均測驗成績是多少能夠用AVG(Result)……