五、子查詢與連接

5-1 數據準備

創建數據庫

CREATE TABLE IF NOT EXISTS tdb_goods(
    goods_id    SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
    goods_name  VARCHAR(150) NOT NULL,
    goods_cate  VARCHAR(40)  NOT NULL,
    brand_name  VARCHAR(40)  NOT NULL,
    goods_price DECIMAL(15,3) UNSIGNED NOT NULL DEFAULT 0,
    is_show     BOOLEAN NOT NULL DEFAULT 1,
    is_saleoff  BOOLEAN NOT NULL DEFAULT 0
  );

如果中文顯示爲亂碼,或者無法插入中文,則設置客戶端的編碼方式,與數據無關

SET NAMES gbk;

寫入記錄

NSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('R510VC 15.6英寸筆記本','筆記本','華碩','3399',DEFAULT,DEFAULT);
 
 INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('Y400N 14.0英寸筆記本電腦','筆記本','聯想','4899',DEFAULT,DEFAULT);
 
 INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('G150TH 15.6英寸遊戲本','遊戲本','雷神','8499',DEFAULT,DEFAULT);
 
 INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('X550CC 15.6英寸筆記本','筆記本','華碩','2799',DEFAULT,DEFAULT);
 
INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('X240(20ALA0EYCD) 12.5英寸超極本','超級本','聯想','4999',DEFAULT,DEFAULT);
 
 INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('U330P 13.3英寸超極本','超級本','聯想','4299',DEFAULT,DEFAULT);
 
 INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('SVP13226SCB 13.3英寸觸控超極本','超級本','索尼','7999',DEFAULT,DEFAULT);
 
 INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('iPad mini MD531CH/A 7.9英寸平板電腦','平板電腦','蘋果','1998',DEFAULT,DEFAULT);
 
 INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('iPad Air MD788CH/A 9.7英寸平板電腦 (16G WiFi版)','平板電腦','蘋果','3388',DEFAULT,DEFAULT);
 
 INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES(' iPad mini ME279CH/A 配備 Retina 顯示屏 7.9英寸平板電腦 (16G WiFi版)','平板電腦','蘋果','2788',DEFAULT,DEFAULT);
 
 INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('IdeaCentre C340 20英寸一體電腦 ','臺式機','聯想','3499',DEFAULT,DEFAULT);
 
 INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('Vostro 3800-R1206 臺式電腦','臺式機','戴爾','2899',DEFAULT,DEFAULT);
 
 INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('iMac ME086CH/A 21.5英寸一體電腦','臺式機','蘋果','9188',DEFAULT,DEFAULT);
 
 INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('AT7-7414LP 臺式電腦 (i5-3450四核 4G 500G 2G獨顯 DVD 鍵鼠 Linux )','臺式機','宏碁','3699',DEFAULT,DEFAULT);
 
 INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('Z220SFF F4F06PA工作站','服務器/工作站','惠普','4288',DEFAULT,DEFAULT);
 
 INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('PowerEdge T110 II服務器','服務器/工作站','戴爾','5388',DEFAULT,DEFAULT);
 
 INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('Mac Pro MD878CH/A 專業級臺式電腦','服務器/工作站','蘋果','28888',DEFAULT,DEFAULT);
 
 INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES(' HMZ-T3W 頭戴顯示設備','筆記本配件','索尼','6999',DEFAULT,DEFAULT);

 INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('商務雙肩揹包','筆記本配件','索尼','99',DEFAULT,DEFAULT);

 INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('X3250 M4機架式服務器 2583i14','服務器/工作站','IBM','6888',DEFAULT,DEFAULT);
 
 INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('玄龍精英版 筆記本散熱器','筆記本配件','九州風神','',DEFAULT,DEFAULT);

 INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES(' HMZ-T3W 頭戴顯示設備','筆記本配件','索尼','6999',DEFAULT,DEFAULT);

 INSERT tdb_goods (goods_name,goods_cate,brand_name,goods_price,is_show,is_saleoff) VALUES('商務雙肩揹包','筆記本配件','索尼','99',DEFAULT,DEFAULT);

 

5-2 子查詢簡介

子查詢是指出現在【其他SQL語句內】的SELECT子句

eg:

SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);

其中,SELECT * FROM t1 ...稱爲Outer Query[外查詢](或者Outer Statement)

SELECT column1 FROM t2 稱爲Sub Query[子查詢]

  • 子查詢指嵌套在【查詢內部】,且必須始終出現在【圓括號內】。
  • 子查詢可以包含多個關鍵字或者條件,如DISTINCT,GROUP BY,ORDER BY,LIMIT,函數等
  • 子查詢的外層查詢可以是:【SELECT,INSERT,UPDATE,SET或DO】
  • 子查詢可以返回值:標量、一行、一列或者子查詢

 

5-3由比較運算符引發的子查詢

單獨分析篩選時

 

SELECT AVG(goods_price) FROM tdb_goods; //AVG函數代表求其平均值//

SELECT ROUND(AVG(goods_price),2) FROM tdb_goods; //round(@,#)代表輸出格式爲@數小數點後#位輸出//

SELECT goods_id,goods_name,goods_price FROM tdb_goods WHERE goods_price>=5391.30; //輸出價格大於5391.30的id、name、price//

綜合起來運用子查詢時

ELECT goods_id,goods_name,goods_price FROM tdb_goods WHERE goods_price>=(SELECT ROUND(AVG(goods_price),2) FROM tdb_goods); //查找價格大於平均值的商品//

SELECT goods_price FROM tdb_price WHERE goods_cate='超級本'\G; //檢索結果非唯一//

對於ANY、SOME、ALL的用法各有不同

SELECT goods_id,goods_name,goods_price FROM tdb_goods WHERE goods_price>=ANY (SELECT goods_price FROM tdb_goods WHERE goods_cate='超級本');

SELECT goods_id,goods_name,goods_price FROM tdb_goods WHERE goods_price>=ALL (SELECT goods_price FROM tdb_goods WHERE goods_cate='超級本');

SELECT goods_id,goods_name,goods_price FROM tdb_goods WHERE goods_price>=SOME (SELECT goods_price FROM tdb_goods WHERE goods_cate='超級本');

 

5-4 由[NOT] IN/EXISTS引發的子查詢

子查詢---in not in

  • in 相當於=any
  • not in 相當於 !=all 或者<>all ——不等於、不包含

子查詢----exists not exists ——用得比較少

  • 如果子查詢返回任何行 exists返回true 否則返回 false

 = ANY 或 = SOME 等價於 IN

SELECT goods_id,goods_name,goods_price FROM tdb_goods WHERE goods_price IN (SELECT goods_price FROM tdb_goods WHERE goods_cate = '超級本')

 

5-5使用INSERT...SELECT插入記錄

INSERT [INTO] tbl_name SET col_name={exprDEFAULT},...//可以使用子查詢

INSERT [INTO] tbl_name [(col_name,...)] SELECT ...//將查詢結果寫入數據表

Eg:

INSERT INTO table_name [(column_name)] SELECT column_name2 FROM table_name2 GROUP BY column_name3;

創建商品分類表

CREATE TABLE IF NOT EXISTS tdb_goods_cates(

cate_id SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,

cate_name VARCHAR(40) NOT NULL

);

 

SELECT goods_cate FROM tdb_goods GROUP BY goods_cate; //列出所有品牌cate

DESC tdb_goods_cates; //顯示出tdb_goods_cates表中的項目名稱,與SHOW COLUMNS FROM tdb_goods_cates;作用相同

INSERT tdb_goods_cates(cate_name) SELECT goods_cate FROM tdb_goods GROUP BY goods_cate;//在表tdb_goods_cates中插入tdb_goods中的cate

 

5-6多表更新

UPDATE table_references SET col_name1={expr1 | DEFAULT} [,col_name2={expr2 | DEFAULT}]... [WHERE where_condition]

  • INNER JOIN,內連接
  • 在MySQL中,JOIN, CROSS JOIN 和 INNER JOIN 是等價的。
  • LEFT [OUTER] JOIN ,左外連接
  • RIGHT [OUTER] JOIN,右外連接

update tdb_goods inner join tdb_goods_cates on goods_cate=cate_name set goods_cate=cate_id;

  • tdb_goods:想要更改的表名
  • inner join: 內連接
  • tdb_goods_cates: 關聯的附表
  • goods_cate=cate_name 兩個表對應列的關係
  • goods_cate=cate_id; 設置 值

 

5-7 多表更新之一步到位

建表、查詢、寫入三合一

CREATE TABLE tdb_goods_brands (

brand_id SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,

brand_name VARCHAR(40) NOT NULL

)

SELECT brand_name FROM tdb_goods GROUP BY brand_name;

多表更新

UPDATE tdb_goods AS g INNER JOIN tdb_goods_brands AS b ON g.brand_name = b.brand_name SET g.brand_name = b.brand_id;

通過ALTER TABLE語句修改數據表結構

ALTER TABLE tdb_goods

CHANGE goods_cate cate_id SMALLINT UNSIGNED NOT NULL,

CHANGE brand_name brand_id SMALLINT UNSIGNED NOT NULL;

  • PS:外鍵,不一定是物理的外鍵,邏輯的外鍵也行,當然,物理外鍵更能保證數據的完整性和一致性。 數字類型的字段佔用的空間更小,查詢的效率也更高。

 

5-8 連接的語法結構

MySQL在SELECT語句、多表更新、多表刪除語句中支持JOIN操作。

table reference A

{[INNER|CROSS] JOIN | {LEFT|RIGHT} [OUTER] JOIN}

table_reference B

ON condition_expr

數據表參照

table_reference

tbl_name [[AS] alias] | table_subquery [AS] alias

數據表可以使用tbl_name AS alias_name 或 tbl_name alias_name賦予別名。

table_subquery可以作爲子查詢使用在FROM子句中,這樣的子查詢必須爲其賦予別名。

 

5-9 內連接INNER JOIN

 

  • 在MySQL中JOIN,INNER JOIN,CROSS JOIN是等價的
  • 交集 僅顯示A、B兩表符合連接條件的記錄。不符合連接條件的記錄不顯示。

 

5-10外鏈接 OUTER JOIN

  • LEFT JOIN:顯示左表全部和左右符合連接條件的記錄
  • RIGHT JOIN:顯示左右符合連接條件的記錄和右表全部記錄
  • 若某字段只存在某一表,則另一表的裏字段返回null

 

5-11多表連接

  • 多表的連接跟兩張表的連接一樣

SELECT A.a,B.b,C.c

FROM tabA

JOIN tabB ON conditonal_expr 

JOIN tabC ON conditonal_expr

 

5-12關於連接的幾點說明

外連接:

以左外連接爲例:

A LEFT JOIN B join_condition

  • 數據表B的結果集依賴於數據表A
  • 數據表A的結果集根據左連接條件依賴所有數據表(B表除外)
  • 左外連接條件決定如何檢索數據表B(在沒有指定WHERE條件的情況下)
  • 如果數據表A的某條記錄符合WHERE條件,但是在數據表B不存在符合連接條件的記錄,將生成一個所有列爲空的額外的B行

內連接:

  • 使用內連接查找的記錄在連接數據表中不存在,並且在WHERE子句中嘗試以下操作:
  • column_name IS NULL 。如果 column_name 被指定爲 NOT NULL,MySQL將在找到符合連接着條件的記錄後停止搜索更多的行(查找衝突)

 

5-13無限級分類表設計

 CREATE TABLE tdb_goods_types(
     type_id   SMALLINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
     type_name VARCHAR(20) NOT NULL,
     parent_id SMALLINT UNSIGNED NOT NULL DEFAULT 0
  ); 

 

無限分類

  • 即在同一張表中既有父類,又有子類
  • 通過在分類表中再增加多一個字段標識其屬於哪一個父類的 ID 來實現
  • 可以通過對同一張數據表的自身連接來進行查詢,需要對錶標識別名

查找顯示父級id對應的名稱

select s.type_id ,s.type_name,p.type_name As parent_id from tdb_goods_types s left join

tdb_goods_types p on s.parent_id=p.type_id;

查找子級對應的名稱

select p.type_id ,p.type_name,s.type_name from tdb_goods_types p left join

tdb_goods_types s on p.type_id=s.parent_id;

查找有多少子級

select p.type_id ,p.type_name,COUNT(s.type_name) from tdb_goods_types p left join

tdb_goods_types s on p.type_id=s.parent_id

GROUP BY p.type_name ORDER BY p.type_id;

 

5-14多表刪除

delete t1 from tdb_goods as t1 //從本表中刪除,將tdb_goods看做t1

left join (select goods_id,goods_name from tdb_goods group by goods_name having count(goods_name)>=2) as t2 //子查詢得到重複條目

on t1.goods_name=t2.goods_name //t1和t2的連接條件

where t1.goods_id>t2.goods_id; //刪除id號較大的條目

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章