查詢中的查詢。P379
如果想把甲的查詢結果作爲乙的查詢輸入,就該子查詢出場。
子查詢有助於避免數據重複,讓查詢更加動態靈活。
Greg不想把招聘服務信息存在my_contacts表中,一是並非所有表裏的人都對此感興趣。二是想要只讓特定人訪問這些敏感信息。
比如添加了 追蹤理想職務和理想薪資的表,還有追蹤聯絡人當前職務和當前薪資的表,還有一個職務空缺信息的表。
這些表和my_contacts 表是有一對一關係的,用自然聯接就可以了。P381
比如
要找網站開發員,
年薪 9.5w - 10.5w
經驗5年以上。
該怎麼設計數據庫的查詢呢?
==========================================
首先選出 job_listings表中所有的職位空缺:
SELECT title FROM job_listings
GROUP BY title ORDER BY title;
還記得 GROUP BY 嗎?不記得回頭看看去。
現在使用關鍵字 IN ,檢查他的聯絡人清單中是否存貯了符合職務需求的人才。
SELECT mc.first_name, mc.last_name, mc.phone, jc.title
FROM job_current AS jc NATURE JOIN my_contacts AS mc
WHERE jc.title IN ('Cook', 'Hairdresser', 'Waiter', 'Web Designer', 'Web Developer');
IN: 如果列表中的 jc.title 屬於括號裏面的職缺之一,IN 就會返回該行。
但是現在我們還是執行了兩段查詢,有什麼辦法只用一段查詢呢?
==============================================================
想用一個查詢完成兩個查詢的工作,我們要在查詢中添加 子查詢。
前一頁的第二個查詢從 my_contacts 和 job_current 中取出職務符合所需職缺的人的信息,這裏的查詢叫 外層查詢。
它裏面有個內層查詢。
也就是說,('Cook', 'Hairdresser'...)之類的可以用一個內層查詢代替。
SELECT title FROM job_listings;
現在,合二爲一:
SELECT mc.first_name, mc.last_name, mc.phone, jc.title
FROM job_current AS jc NATURE JOIN my_contacts AS mc
WHERE jc.title IN (SELECT title FROM job_listings);
這樣搞定~
======================================================================
子查詢就是查詢中的查詢。P388
還可以舉例:
SELECT some_column, another_column
FROM table
WHERE column = (SELECT coumn FROM table);
======================================================================
再舉個例子,查詢郵政編碼的。
首先子查詢接受來自 zip_code 的標量值。然後再 WHERE 子句中尋找這個值。
SELECT last_name, first_name
FROM my_contacts
WHERE zip_code = (
SELECT zip_code
FROM zip_code
WHERE city = 'Memphis' AND state = 'TN');
相同的查詢也可以用聯接完成,但是可能子查詢簡單一些:
SELECT last_name, first_name
FROM my_contacts mc
NATURE JOIN zip_code zc
WHERE zc.city = 'Memphis'
AND zc.state = 'TN';
運用別名會更簡單。
比如上面的 zc
=====================================================
子查詢難的地方不是結構,而是要知道什麼時候需要子查詢。
我們可以用MAX(salary)舉例:
SELECT MAX(salary) FROM job_current;
繼續分解查詢,第一個部分:
SELECT mc.first_name, mc.last_name
FROM my_contacts AS mc;
最後找出串起兩個查詢的方式:
SELECT mc.first_name, mc.last_name, jc.salary
FROM my_contacts AS mc
NATURE JOIN job_current AS jc;
接下來加上 WHERE子句來連接兩段查詢:
SELECT mc.first_name, mc.last_name, jc.salary
FROM my_contacts AS mc
NATURE JOIN job_current AS jc
WHERE jc.salary =
(SELECT MAX()jc.salary) FROM job_current jc;
=================================================================
當然也可以用自然內聯接和 LIMIT 命令完成。
==================================================================
子查詢也可以作爲 SELECT 選取的列,比如:
SELECT mc.first_name, mc.last_name,
(SELECT state
FROM zip_code
WHERE mc.zip_code = zip_code) AS state
FROM my_contacts mc;
這裏子查詢就是查找 mc 的每一行,取出每一行的州名。
子查詢只能返回一個值,每返回一個值,整個查詢也返回一行,以下爲結果:
=========================================================
目前我們看到的都是非關聯子查詢。軟件先處理內層查詢,再用於外層查詢的 WHERE。
內層查詢不依賴於外層查詢的值,這稱爲非關聯子查詢。
有多個值的非關聯子查詢: IN, NOT IN
SELECT mc.first_name, mc.last_name, mc.phone, jc.title
FROM job_current AS jc NATURE JOIN my_contacts AS mc
WHERE jc.title IN (SELECT title FROM job_listings);
這個命令是協助找出符合職缺列表需求的職務。這個查詢接受整個 title 集並評估 當前job 表中的每一行,尋找潛在的匹配記錄。
使用 NOT IN 可以找出不符合職缺列表的職務。
SELECT mc.first_name, mc.last_name, mc.phone, jc.title
FROM job_current AS jc NATURE JOIN my_contacts AS mc
WHERE jc.title NOT IN (SELECT title FROM job_listings);
=======================================================================
關聯子查詢:
關聯子查詢是指內層查詢的解析需要依賴外層查詢的結果。
例如:
SELECT mc.first_name, mc.last_name
FROM my_contacts AS mc
WHERE
3 = (
SELECT COUNT(*) FROM contact_interest
WHERE contact_id = mc.contact_id
);
==================================================================
搭配 NOT EXISTS 的關聯子查詢:
SELECT mc.first_name firstname, mc.last_name lastname, mc.email email
FROM my_contacts mc
WHERE NOT EXISTS
(SELECT * FROM job_current jc
WHERE mc.contact_id = jc.contact_id);
NOT EXISTS 負責從 mc 表中找出姓名與電子郵件地址,他們都沒列在 job_current 中。
===========================================================================
EXISTS 與 NOT EXISTS
SELECT mc.first_name firstname, mc.last_name lastname, mc.email email
FROM my_contacts mc
WHERE EXISTS
(SELECT * FROM contact_interest ci WHERE mc.contact_id = ci.contact_id);
找出曾出現在 contact_interest 表中的人
============================================================================
這些工具還可以用在 INSERT,UPDATE,DELETE語句中~