天天看點

mysql查詢、子查詢、連接配接查詢

mysql查詢、子查詢、連接配接查詢

where子句(條件查詢):按照“條件表達式”指定的條件進行查詢。

group by子句(分組):按照“屬性名”指定的字段進行分組。group by子句通常和count()、sum()等聚合函數一起使用。

having子句(篩選):有group by才能having子句,隻有滿足“條件表達式”中指定的條件的才能夠輸出。

order by子句(排序):按照“屬性名”指定的字段進行排序。排序方式由“asc”和“desc”兩個參數指出,預設是按照“asc”來排序,即升序。

limit(限制結果集)。

1、where——基礎查詢

where常用運算符:

mysql查詢、子查詢、連接配接查詢

2、group by 分組

“Group By”從字面意義上了解就是根據“By”指定的規則對資料進行分組,所謂的分組就是将一個“資料集”劃分成若幹個“小區域”,然後針對若幹個“小區域”進行資料處理。

注:group by語句中select指定的字段必須是“分組依據字段”,其他字段若想出現在select中則必須包含在聚合函數中。

mysql中五種常用的聚合函數:

(1)max(列名):求最大值。

(2)min(列名):求最小值。

(2)sum(列名):求和。

(4)avg(列名):求平均值。

(5)count(列名):統計記錄的條數。

3、having

having子句可以讓我們篩選成組後的各種資料,where子句在聚合前先篩選記錄,也就是說作用在group by和having子句前。而 having子句在聚合後對組記錄進行篩選。 

示例:

示例:Having和Where的聯合使用方法

where和having的差別:

作用的對象不同。WHERE 子句作用于表和視圖,HAVING 子句作用于組。

WHERE 在分組和聚集計算之前選取輸入行(是以,它控制哪些行進入聚集計算), 而 HAVING 在分組和聚集之後選取分組的行。是以,WHERE 子句不能包含聚集函數; 因為試圖用聚集函數判斷那些行輸入給聚集運算是沒有意義的。 相反,HAVING 子句總是包含聚集函數。(嚴格說來,你可以寫不使用聚集的 HAVING 子句, 但這樣做隻是白費勁。同樣的條件可以更有效地用于 WHERE 階段。)

在上面的例子中,我們可以在 WHERE 裡應用數量字段來限制,因為它不需要聚集。 這樣比在 HAVING 裡增加限制更加高效,因為我們避免了為那些未通過 WHERE 檢查的行進行分組和聚集計算。

綜上所述:

having一般跟在group by之後,執行記錄組選擇的一部分來工作的。where則是執行所有資料來工作的。

再者having可以用聚合函數,如having sum(qty)>1000

例子:where + group by + having + 函數 綜合查詢

練習表:

mysql查詢、子查詢、連接配接查詢

查詢目的如下:

查詢出兩門及兩門以上不及格者的平均成績(注意是所有科目的平均成績)

錯誤情況1:題意了解錯誤,了解成查出不及格科目的平均成績。

mysql查詢、子查詢、連接配接查詢

count(a),無論a是什麼,都隻是數一行;count時,每遇到一行,就數一個a,跟條件無關!

正解:count(score<60)達不到想要的結果,并不是條件的問題,而是無論count()裡的表達式是什麼都會數一行。score<60 傳回 1 或 0;

是以可以用sum(score<60)來計算不及格的科目數!

mysql查詢、子查詢、連接配接查詢

4、order by 排序

(1)order by price  //預設升序排列

(2)order by price desc //降序排列

(3)order by price asc //升序排列,與預設一樣

(4)order by rand() //随機排列,效率不高

5、limit

limit [offset,] N

offset 偏移量,可選,不寫則相當于limit 0,N

N  取出條目

示例:取價格第4-6高的商品

總結:

select子句順序

mysql查詢、子查詢、連接配接查詢

1、where型子查詢(把内層查詢結果當作外層查詢的比較條件)

(1)查詢id最大的一件商品(使用排序+分頁實作)

(2)查詢id最大的一件商品(使用where子查詢實作)

(3)查詢每個類别下id最大的商品(使用where子查詢實作)

2、from型子查詢(把内層的查詢結果當成臨時表,供外層sql再次查詢。查詢結果集可以當成表看待。臨時表要使用一個别名。)

(1)查詢每個類别下id最大的商品(使用from型子查詢)

子查詢查出的結果集看第二張圖,可以看到每個類别的第一條的商品id都為該類别下的最大值。然後将這個結果集作為一張臨時表,巧妙的使用group by 查詢出每個類别下的第一條記錄,即為每個類别下商品id最大。

mysql查詢、子查詢、連接配接查詢
mysql查詢、子查詢、連接配接查詢

3、exists型子查詢(把外層sql的結果,拿到内層sql去測試,如果内層的sql成立,則該行取出。内層查詢是exists後的查詢。)

(1)從類别表中取出其類别下有商品的類别(如果該類别下沒有商品,則不取出)[使用where子查詢]

(2)從類别表中取出其類别下有商品的類别(如果該類别下沒有商品,則不取出)[使用exists子查詢]

exists子查詢,如果exists後的内層查詢能查出資料,則表示存在;為空則不存在。

mysql查詢、子查詢、連接配接查詢

學習連接配接查詢,先了解下"笛卡爾積",看下百度給出的解釋:

mysql查詢、子查詢、連接配接查詢

      在資料庫中,一張表就是一個集合,每一行就是集合中的一個元素。表之間作聯合查詢即是作笛卡爾乘積,比如A表有5條資料,B表有8條資料,如果不作條件篩選,那麼兩表查詢就有 5 X 8 = 40 條資料。

先看下用到的測試表基本資訊:我們要實作的功能就是查詢商品的時候,從類别表将商品類别名稱關聯查詢出來。

行數:類别表14條,商品表4條。

mysql查詢、子查詢、連接配接查詢

結構:商品表和類别表都有一個cat_id

mysql查詢、子查詢、連接配接查詢

1、全相乘(不是全連接配接、連接配接查詢),全相乘是作笛卡爾積

兩表全相乘,就是直接從兩張表裡查詢;從查詢的截圖看出,總共查出了 4 X 14 = 56 條記錄,這些記錄是笛卡爾乘積的結果,即兩兩組合;

但我們要的是每個商品資訊顯示類别名稱而已,這裡卻查出了56條記錄,其中有52條記錄都是無效的資料,全相乘的查詢效率低。

mysql查詢、子查詢、連接配接查詢

如果在兩張表裡有相同字段,做聯合查詢的時候,要差別表名,否則會報錯誤(模糊不清)。

mysql查詢、子查詢、連接配接查詢

       添加條件,使兩表關聯查詢,這樣查出來就是商品和類别一一對應了。雖然這裡查出來4條記錄,但是全相乘效率低,全相乘會在記憶體中生成一個非常大的資料(臨時表),因為有很多不必要的資料。

    如果一張表有10000條資料,另一張表有10000條資料,兩表全相乘就是100W條資料,是非常消耗記憶體的。而且,全相乘不能好好的利用索引,因為全相乘生成一張臨時表,臨時表裡是沒有索引的,大大降低了查詢效率。

mysql查詢、子查詢、連接配接查詢

2、左連接配接查詢 left join ... on ...

文法:

假設有A、B兩張表,左連接配接查詢即 A表在左不動,B表在右滑動,A表與B表通過一個關系來關聯行,B表去比對A表。

2.1、先來看看on後的條件恒為真的情況

     跟全相乘相比,從截圖可以看出,總記錄數仍然不變,還是 4 X 14 = 56 條記錄。但這次是商品表不動,類别表去比對,因為每次都為真,是以将所有的記錄都查出來了。左連接配接,其實就可以看成左表是主表,右表是從表。

mysql查詢、子查詢、連接配接查詢

2.2 、根據cat_id使兩表關聯行

使用左連接配接查詢達到了同樣的效果,但是不會有其它備援資料,查詢速度快,消耗記憶體小,而且使用了索引。左連接配接查詢效率相比于全相乘的查詢效率快了10+倍以上。

  左連接配接時,mingoods表(左表)不動,category表(右表)根據條件去一條條比對,雖說category表也是讀取一行行記錄,然後判斷cat_id是否跟mingoods表的相同,但是,左連接配接使用了索引,cat_id建立了索引的話,查詢速度非常快,是以整體效率相比于全相乘要快得多,全相乘沒有使用索引。

mysql查詢、子查詢、連接配接查詢

2.3、查詢出第四個類别下的商品,要求顯示商品名稱

mysql查詢、子查詢、連接配接查詢

2.4 、對于左連接配接查詢,如果右表中沒有滿足條件的行,則預設填充NULL。

mysql查詢、子查詢、連接配接查詢

3、右連接配接查詢 right join ... on ...

右連接配接查詢跟左連接配接查詢類似,隻是右連接配接是以右表為主表,會将右表所有資料查詢出來,而左表則根據條件去比對,如果左表沒有滿足條件的行,則左邊預設顯示NULL。左右連接配接是可以互換的。

mysql查詢、子查詢、連接配接查詢

4、内連接配接查詢 inner join ... on ...

内連接配接查詢,就是取左連接配接和右連接配接的交集,如果兩邊不能比對條件,則都不取出。

mysql查詢、子查詢、連接配接查詢

5、全連接配接查詢 full join ... on ...

全連接配接會将兩個表的所有資料查詢出來,不滿足條件的為NULL。

全連接配接查詢跟全相乘查詢的差別在于,如果某個項不比對,全相乘不會查出來,全連接配接會查出來,而連接配接的另一邊則為NULL。

6、聯合查詢 union

union是求兩個查詢的并集。union合并的是結果集,不區分來自于哪一張表,是以可以合并多張表查詢出來的資料。

mysql查詢、子查詢、連接配接查詢

6.1、将兩張表的資料合并查詢出來

mysql查詢、子查詢、連接配接查詢

6.2、union查詢,列名不一緻時,以第一條sql語句的列名對齊

mysql查詢、子查詢、連接配接查詢

6.3、使用union查詢會将重複的行過濾掉

mysql查詢、子查詢、連接配接查詢

6.4、使用union all查詢所有,重複的行不會被過濾

mysql查詢、子查詢、連接配接查詢

6.5、union查詢,如果列數不相等,會報列數不相等錯誤

mysql查詢、子查詢、連接配接查詢

6.6、union 後的結果集還可以再做篩選

mysql查詢、子查詢、連接配接查詢

 union查詢時,order by放在内層sql中是不起作用的;因為union查出來的結果集再排序,内層的排序就沒有意義了;是以,内層的order by排序,在執行期間,被mysql的代碼分析器給優化掉了。

mysql查詢、子查詢、連接配接查詢

order by 如果和limit一起使用,就顯得有意義了,就不會被優化掉。

mysql查詢、子查詢、連接配接查詢

6.7、練習

mysql查詢、子查詢、連接配接查詢
mysql查詢、子查詢、連接配接查詢

連接配接查詢總結:

1、在資料庫中,一張表就是一個集合,每一行就是集合中的一個元素。連接配接查詢即是作笛卡爾積,比如A表有1W條資料,B表有1W條資料,那麼兩表查詢就有 1W X 1W = 100W 條資料 

2、如果在兩張表裡有相同字段,做聯合查詢的時候,要差別表名,否則會報錯誤(ambiguous 模糊不清)

3、全相乘效率低,全相乘會在記憶體中生成一個非常大的資料(臨時表),因為有很多不必要的資料。

 如果一張表有10000條資料,另一張表有10000條資料,兩表全相乘就是100W條資料,是非常消耗記憶體的。

而且,全相乘不能好好的利用索引,因為全相乘生成一張臨時表,臨時表裡是沒有索引的,大大降低了查詢效率。

4、左連接配接查詢時,以左表為主表,會将左表所有資料查詢出來;左表不動,右表根據條件去一條條比對,如果沒有滿足條件的記錄,則右邊傳回NULL。

右連接配接查詢值,以右表為主表,會将右表所有資料查詢出來,右表不動,左表則根據條件去比對,如果左表沒有滿足條件的行,則左邊傳回NULL。 

左右連接配接是可以互換的:A left join B  ==  B right join A (都是以A為主表) 。

左右連接配接既然可以互換,出于移植相容性方面的考慮,盡量使用左連接配接。

5、連接配接查詢時,雖說也是讀取一行行記錄,然後判斷是否滿足條件,但是,連接配接查詢使用了索引,條件列建立了索引的話,查詢速度非常快,是以整體效率相比于全相乘要快得多,全相乘是沒有使用索引的。

使用連接配接查詢,查詢速度快,消耗記憶體小,而且使用了索引。連接配接查詢效率相比于全相乘的查詢效率快了10+倍以上。

6、内連接配接查詢,就是取左連接配接和右連接配接的交集,如果兩邊不能比對條件,則都不取出。

7、MySql可以用union(聯合查詢)來查出左連接配接和右連接配接的并集。

union查詢會過濾重複的行,union all 不會過濾重複的行。

union查詢時,union之間的sql列數必須相等,列名以第一條sql的列為準;列類型可以不一樣,但沒太大意義。

union查詢時,order by放在内層sql中是不起作用的;因為union查出來的結果集再排序,内層的排序就沒有意義了;是以,内層的order by排序,在執行期間,被mysql的代碼分析器給優化掉了。

 但是,order by 如果和limit一起使用,就顯得有意義了,會影響最終結果集,就不會被優化掉。order by會根據最終是否會影響結果集而選擇性的優化。

注:union和union all的差別,union會去掉重複的記錄,在結果集合并後悔對新産生的結果集進行排序運算,效率稍低,union all直接合并結果集,如果确定沒有重複記錄,建議使用union all。

8、 LEFT JOIN 是 LEFT OUTER JOIN 的縮寫,同理,RIGHT JOIN 是 RIGHT OUTER JOIN 的縮寫;JOIN 是 INNER JOIN 的縮寫。

1、使用join關鍵字關聯查詢

(1)、内連接配接(inner join)

連接配接兩張表,連接配接條件使用on關鍵字,内連接配接隻會顯示比對的資料記錄。

eg:查詢學生姓名、科目、分數

mysql查詢、子查詢、連接配接查詢

(2)、左連接配接(left join)

傳回左表中所有記錄以及右表中符合連接配接條件的所有記錄。

eg: 使用左連接配接查詢學生姓名、科目、分數

mysql查詢、子查詢、連接配接查詢

(3)、右連接配接(right join)

傳回右表中所有記錄以及左表中符合連接配接條件的所有記錄。

eg:使用右連接配接查詢學生姓名、科目、分數

mysql查詢、子查詢、連接配接查詢

注:内外連接配接差別:内連接配接隻會顯示比對的資料記錄,外連接配接例如左連接配接會把左邊表中所有記錄顯示出來,即使在右邊表中沒有比對記錄也會顯示左表的資料,右連接配接反之。

2、使用表和表之間相同id關聯查詢

這種關聯方式和内連接配接一樣,隻會顯示出比對的資料

mysql查詢、子查詢、連接配接查詢