資料查詢之連線查詢、子查詢和聯合查詢
阿新 • • 發佈:2018-11-15
一、連線查詢
- 基本含義:將兩個以上的表(資料來源),連線起來成為一個數據源。
- 基本形式:from 表1 [連線方式] join 表2 [on 連線條件]
- join 為連線查詢關鍵字--必須
- [連線方式] [on 連線條件]為可選性
- 交叉連線: from 表1 [cross] join 表2
- 交叉連線為兩兩橫向連線,假如表1有m條記錄,表2有n條記錄,則交叉連線後有m*n條記錄
- 示例:
內連線: from 表1 [inner] join 表2 on 連線條件;在交叉連線基礎上,選取符合on 連線條件的記錄
- on 連線條件 為內連線必選項
- 示例:
- 左外連線:from 表1 left [outer] join 表2 on 連線條件;內連線基礎上,加上表1中不符合條件的記錄(右側部分全為null)
- 示例:
- 右外連線:from 表1 right [outer] join 表2 on 連線條件;內連線基礎上,加上表2中不符合條件的記錄(右側部分全為null)
- 示例:
- 在時間應用中,交叉連線結果並不是都具有實際意義,更過使用的是內連線,舉例:
- 表1:商品資訊表(production)
mysql> select * from production;
- 表2:商品型別表(product_type)
mysql> select * from product_type; +------------+--------------+ | protype_id | protype_name | +------------+--------------+ | 1 | 家用電器 | | 2 | 手機數碼 | | 3 | 電腦辦公 | | 4 | 圖書音像 | | 5 | 家居傢俱 | | 6 | 服飾配飾 | | 7 | 個護化妝 | | 8 | 運動戶外 | | 9 | 汽車用品 | | 10 | 食品酒水 | | 11 | 營養保健 | +------------+--------------+ 11 rows in set (0.01 sec)
- 請給出索尼 4G手機所屬商品型別名稱:
-
mysql> select protype_name from production as p1 join product_type as p2 on p1.type=p2.protype_id wh ere p1.name like '%SONY%'and p1.name like '%4G%'; +--------------+ | protype_name | +--------------+ | 手機數碼 | +--------------+ 1 row in set (0.00 sec)
-
- 表1:商品資訊表(production)
二、子查詢
- 基本含義
- 一般一個查詢,就出現一次select 語句,但如果又出現select 語句,此時就稱後者為‘子查詢’,前者為‘主查詢’
- 形式
- select 欄位或者表示式或者(子查詢1) [as 別名] from 表名或者(子查詢2) where 欄位或者表示式或者子(查詢3)
- 通常每個位置的子查詢,應該符合該位置的資料需求
- 子查詢1 應該是一個‘資料結果’
- 子查詢2 可以是‘任意結果’
- 子查詢3 可以是一個數據或者一列資料
- 按結果分類
- 表子查詢:子查詢結果為‘多行多列’,通常可以當做‘表’放在from 後面使用
- 行子查詢:子查詢結果為‘一行多列’,通常可以當做‘行’來使用,放在‘行比較語法’
- 列子查詢:子查詢結果為‘多行一列’,通常可以當做‘多個值’來使用,類似(1,3,33,66)
- 標量子查詢:子查詢結果為‘一行一列’,通常可以當做‘一個值’來使用,當做欄位使用
- 常見子查詢及相關關鍵字
- 比較運算子中使用子查詢
- 形式: 運算元 比較運算子 (標量子查詢);運算元通常為一個欄位
- 含義:判斷運算元(欄位)的值是否滿足比較運算子所設定的結果
- 舉例:表
mysql> select * from production; +--------+-----------------------------------+------+-------+-------+--------+ | pro_id | name | type | price | brand | origin | +--------+-----------------------------------+------+-------+-------+--------+ | 1 | 康佳(KONKA)42英寸全高清液晶電視 | 1 | 1999 | 康佳 | 深圳 | | 2 | 索尼(SONY)4G手機(黑色) | 2 | 3238 | 索尼 | 深圳 | | 3 | 海信(Hisense)55英寸智慧電視 | 1 | 4199 | 海信 | 青島 | | 4 | 聯想(Lenovo)14.0英寸膝上型電腦 | 3 | 5499 | 聯想 | 北京 | | 5 | 索尼(SONY)13.3英寸觸控超極本 | 3 | 11499 | 索尼 | 天津 | | 6 | 索尼(SONY)60英寸全高清液晶電視 | 1 | 6999 | 索尼 | 北京 | | 7 | 聯想(Lenovo)12.0英寸膝上型電腦 | 3 | 2999 | 聯想 | 北京 | | 8 | 聯想 雙卡雙待3G手機 | 2 | 988 | 聯想 | 北京 | | 9 | 惠普(HP)黑白鐳射印表機 | 3 | 1169 | 惠普 | 天津 | +--------+-----------------------------------+------+-------+-------+--------+ 9 rows in set (0.00 sec)
- 問題:找出大於平均價的商品
- 第一步:找平均價
-
mysql> select avg(price) from production; +-------------------+ | avg(price) | +-------------------+ | 4287.666666666667 | +-------------------+ 1 row in set (0.00 sec)
-
- 第二步:找商品(大於平均價)
-
mysql> select * from production where price > (select avg(price) from production); +--------+----------------------------------+------+-------+-------+--------+ | pro_id | name | type | price | brand | origin | +--------+----------------------------------+------+-------+-------+--------+ | 4 | 聯想(Lenovo)14.0英寸膝上型電腦 | 3 | 5499 | 聯想 | 北京 | | 5 | 索尼(SONY)13.3英寸觸控超極本 | 3 | 11499 | 索尼 | 天津 | | 6 | 索尼(SONY)60英寸全高清液晶電視 | 1 | 6999 | 索尼 | 北京 | +--------+----------------------------------+------+-------+-------+--------+ 3 rows in set (0.00 sec)
-
- 第一步:找平均價
- 使用in 子查詢
- 形式:where 運算元 in (列子查詢)
- 舉例:問題找出所有帶‘電’字類別的商品
- 第一步:找出帶‘電’字的類別ID
-
mysql> select protype_id from product_type where protype_name like '%電%'; +------------+ | protype_id | +------------+ | 1 | | 3 | +------------+ 2 rows in set (0.00 sec)
-
- 第二步:找商品
-
mysql> select * from production where production.type in (select protype_id from product_type where protype_name like '%電%'); +--------+-----------------------------------+------+-------+-------+--------+ | pro_id | name | type | price | brand | origin | +--------+-----------------------------------+------+-------+-------+--------+ | 1 | 康佳(KONKA)42英寸全高清液晶電視 | 1 | 1999 | 康佳 | 深圳 | | 3 | 海信(Hisense)55英寸智慧電視 | 1 | 4199 | 海信 | 青島 | | 4 | 聯想(Lenovo)14.0英寸膝上型電腦 | 3 | 5499 | 聯想 | 北京 | | 5 | 索尼(SONY)13.3英寸觸控超極本 | 3 | 11499 | 索尼 | 天津 | | 6 | 索尼(SONY)60英寸全高清液晶電視 | 1 | 6999 | 索尼 | 北京 | | 7 | 聯想(Lenovo)12.0英寸膝上型電腦 | 3 | 2999 | 聯想 | 北京 | | 9 | 惠普(HP)黑白鐳射印表機 | 3 | 1169 | 惠普 | 天津 | +--------+-----------------------------------+------+-------+-------+--------+ 7 rows in set (0.00 sec)
-
- 第一步:找出帶‘電’字的類別ID
- 使用any 子查詢
- 形式:where 運算元 比較運算子 any(列子查詢)
- 含義:該運算元的值只要跟列子查詢其中的任意一個值滿足給定的比較運算,就算滿足條件
- 舉例:問題找出所有帶‘電’字類別的商品
mysql> select * from production where production.type = any(select protype_id from product_type wher e -> protype_name like '%電%'); +--------+-----------------------------------+------+-------+-------+--------+ | pro_id | name | type | price | brand | origin | +--------+-----------------------------------+------+-------+-------+--------+ | 1 | 康佳(KONKA)42英寸全高清液晶電視 | 1 | 1999 | 康佳 | 深圳 | | 3 | 海信(Hisense)55英寸智慧電視 | 1 | 4199 | 海信 | 青島 | | 4 | 聯想(Lenovo)14.0英寸膝上型電腦 | 3 | 5499 | 聯想 | 北京 | | 5 | 索尼(SONY)13.3英寸觸控超極本 | 3 | 11499 | 索尼 | 天津 | | 6 | 索尼(SONY)60英寸全高清液晶電視 | 1 | 6999 | 索尼 | 北京 | | 7 | 聯想(Lenovo)12.0英寸膝上型電腦 | 3 | 2999 | 聯想 | 北京 | | 9 | 惠普(HP)黑白鐳射印表機 | 3 | 1169 | 惠普 | 天津 | +--------+-----------------------------------+------+-------+-------+--------+ 7 rows in set (0.00 sec)
- all 子查詢
- 形式:where 運算元 比較運算子 all(列子查詢)
- 含義:該運算元的值必須跟列子查詢其中的所有值滿足給定的比較運算,才算滿足條件
- 舉例:找出價格最高的產品
- 思路一:找出價格大於等於所有價格的商品
mysql> select * from production where price >= all(select price from production); +--------+--------------------------------+------+-------+-------+--------+ | pro_id | name | type | price | brand | origin | +--------+--------------------------------+------+-------+-------+--------+ | 5 | 索尼(SONY)13.3英寸觸控超極本 | 3 | 11499 | 索尼 | 天津 | +--------+--------------------------------+------+-------+-------+--------+ 1 row in set (0.00 sec)
- 思路二:找出最大的價格,對比最大價格找出對應的商品 上文中有提及不在重複
- 思路一:找出價格大於等於所有價格的商品
- some 子查詢
- some 是 any 的同義詞,用法相同
- exists 和 not exists 子查詢
- 形式:where exist (子查詢)
- 含義:如果該子查詢有結果資料(無論什麼資料,只要大於等於1行),則就為true,否則就為false
- 舉例:找出具有在售商品的類別資訊
mysql> select * from product_type where exists(select * from production as p1 where p1.type = produc t_type.protype_id); +------------+--------------+ | protype_id | protype_name | +------------+--------------+ | 1 | 家用電器 | | 2 | 手機數碼 | | 3 | 電腦辦公 | +------------+--------------+ 3 rows in set (0.00 sec)
- 舉例:找出具有沒有在售商品的類別資訊
mysql> select * from product_type where not exists(select * from production as p1 where p1.type = pr oduct_type.protype_id); +------------+--------------+ | protype_id | protype_name | +------------+--------------+ | 4 | 圖書音像 | | 5 | 家居傢俱 | | 6 | 服飾配飾 | | 7 | 個護化妝 | | 8 | 運動戶外 | | 9 | 汽車用品 | | 10 | 食品酒水 | | 11 | 營養保健 | +------------+--------------+ 8 rows in set (0.00 sec)
- 實際上,這種exists 子查詢,如果涉及2個表(或以上),其內部其實會自動進行“連線查詢”,且其邏輯過程較為複雜,而且不明確,通常認為效率較低,儘量少用
- 比較運算子中使用子查詢
三、聯合查詢
- 形式:select 語句1 union select 語句2
- 基本含義:將2個select 語句查詢的結果“層疊”為一個“大結果”
- 說明:
- 具有相同輸出欄位--通常欄位型別也相同,具有現實意義
- 結果集中的欄位以第一個select 語句的輸出欄位為準
- 第一個select 語句的欄位可以做別名,單若果做別名,則後續的where,group,order等子句也要用該別名
- 示例:
mysql> (select * from join1) union (select * from join2); +----+------+------+ | id | f1 | f2 | +----+------+------+ | 1 | a1 | b1 | | 2 | a12 | b2 | | 3 | a3 | b3 | | 11 | a1 | b11 | | 12 | a12 | b12 | | 13 | a13 | b13 | +----+------+------+ 6 rows in set (0.00 sec)