新建一個測試數據庫TestDB;
create database TestDB;
創建測試表table1和table2; CREATE TABLE table1
(
customer_id VARCHAR(10) NOT NULL,
city VARCHAR(10) NOT NULL,
PRIMARY KEY(customer_id)
)ENGINE=INNODB DEFAULT CHARSET=UTF8;
CREATE TABLE table2
(
order_id INT NOT NULL auto_increment,
customer_id VARCHAR(10),
PRIMARY KEY(order_id)
)ENGINE=INNODB DEFAULT CHARSET=UTF8;
插入測試數據; INSERT INTO table1(customer_id,city) VALUES('163','hangzhou');
INSERT INTO table1(customer_id,city) VALUES('9you','shanghai');
INSERT INTO table1(customer_id,city) VALUES('tx','hangzhou');
INSERT INTO table1(customer_id,city) VALUES('baidu','hangzhou');
INSERT INTO table2(customer_id) VALUES('163');
INSERT INTO table2(customer_id) VALUES('163');
INSERT INTO table2(customer_id) VALUES('9you');
INSERT INTO table2(customer_id) VALUES('9you');
INSERT INTO table2(customer_id) VALUES('9you');
INSERT INTO table2(customer_id) VALUES('tx');
准備工作做完以後,table1和table2看起來應該像下面這樣:
mysql> select * from table1;
+-------------+----------+
| customer_id | city |
+-------------+----------+
| 163 | hangzhou |
| 9you | shanghai |
| baidu | hangzhou |
| tx | hangzhou |
+-------------+----------+
4 rows in set (0.00 sec)
mysql> select * from table2;
+----------+-------------+
| order_id | customer_id |
+----------+-------------+
| 1 | 163 |
| 2 | 163 |
| 3 | 9you |
| 4 | 9you |
| 5 | 9you |
| 6 | tx |
+----------+-------------+
7 rows in set (0.00 sec)
准備工作做的差不多了,開始今天的總結吧。
一個問題
現在需要查詢所有杭州用戶的所有訂單號,這個SQL語句怎麼寫?首先,你可以這麼寫:
select table2.customer_id, table2.order_id from table2 join table1 on table1.customer_id=table2.customer_id where table1.city='hangzhou';
能實現我們需要的結果。但是,我們也可以這麼寫:
select customer_id, order_id from table2 where customer_id in (select customer_id from table1 where city='hangzhou');
呃?在()括號中的的select語句是什麼?問題來了,這到底是什麼語法,怎麼也可以完成任務,那麼這篇博文就圍繞著這個問題開始展開。
啥是子查詢
簡單的說,子查詢就是:
子查詢就是指在一個select語句中嵌套另一個select語句。同時,子查詢必須包含括號。
alt
如上圖所示,子查詢,有叫內部查詢,相對於內部查詢,包含內部查詢的就稱為外部查詢。子查詢可以包含普通select可以包括的任何子句,比如:distinct、group by、order by、limit、join和union等;但是對應的外部查詢必須是以下語句之一:select、insert、update、delete、set或者do。
alt
我們可以在where和having子句中使用子查詢,將子查詢得到的結果作為判斷的條件。
使用比較進行子查詢
一個子查詢會返回一個標量(就一個值)、一個行、一個列或一個表,這些子查詢稱之為標量、行、列和表子查詢。
當一個子查詢返回一個標量時,我們就可以在where或者having子句中使用比較符與子查詢得到的結果進行直接判斷。比如,我現在要得到比用戶tx訂單數多的customer_id、city和訂單數,這個sql語句怎麼寫。
先來說說,我寫sql的一般步驟:
讀懂需求;
得到比用戶tx訂單數多的customer_id、city和對應的訂單數。
看看最終需要得到哪些字段信息;
最終需要得到customer_id、city和訂單數信息。
分析這些字段信息涉及到哪幾個表;
涉及到表table1和表table2。
這幾個表是如何關聯的;
表table1和表table2的關聯就在於customer_id字段。
分解需求,得到一個個小的需求;
需要得到tx用戶的訂單數;
需要得到其它用戶的訂單數;
比較訂單數。
確認每一個小需求的過濾條件;
得到每個小需求的結果,進行組裝,得到最終結果。
最終,我會寫出一下的sql語句:
select table1.customer_id,city,count(order_id)
from table1 join table2
on table1.customer_id=table2.customer_id
where table1.customer_id <> 'tx'group by customer_id
having count(order_id) >
(select count(order_id)
from table2
where customer_id='tx'
group by customer_id);
上面的查詢中使用了子查詢,外部查詢與子查詢得到的結果進行了比較判斷。如果子查詢返回一個標量值(就一個值),那麼外部查詢就可以使用:=、>、<、>=、<=和<>符號進行比較判斷;如果子查詢返回的不是一個標量值,而外部查詢使用了比較符和子查詢的結果進行了比較,那麼就會拋出異常。
使用ANY進行子查詢
上面使用比較符進行子查詢,規定了子查詢只能返回一個標量值;但是,如果子查詢返回的是一個集合,怎麼辦?
沒問題,我們可以使用:any、in、some或者all來和子查詢的返回結果進行條件判斷。這裡先總結使用any進行子查詢。
any關鍵詞必須與上面總結的比較操作符一起使用;any關鍵詞的意思是“對於子查詢返回的列中的任何一個數值,如果比較結果為TRUE,就返回TRUE”。
好比“10 >any(11, 20, 2, 30)”,由於10>2,所以,該該判斷會返回TRUE;只要10與集合中的任意一個進行比較,得到TRUE時,就會返回TRUE。
比如,我現在要查詢比customer_id為tx或者9you的訂單數量多的用戶的id、城市和訂單數量。
我可以得到以下的sql語句來完成需求。
select table1.customer_id,city,count(order_id)from table1 join table2
on table1.customer_id=table2.customer_id
where table1.customer_id<>'tx' and table1.customer_id<>'9you'group by customer_id
having count(order_id) >
any (select count(order_id)from table2
where customer_id='tx' or customer_id='9you'group by customer_id);
any的意思比較好明白,直譯就是任意一個,只要條件滿足任意的一個,就返回TRUE。