Head First SQL 第九章

查詢中的查詢。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);


這裏 IN 根據子查詢返回的整個結果集來評估 jc.title 每一行的值。

這個命令是協助找出符合職缺列表需求的職務。這個查詢接受整個 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);


非關聯子查詢使用 IN 或者 NOT IN 來檢查子查詢返回的值是否爲集合的成員之一。
=======================================================================

關聯子查詢:


關聯子查詢是指內層查詢的解析需要依賴外層查詢的結果。

例如:

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
);


mc的別名建立在外層查詢中,內層的子查詢也引用了別名mc,於是外層查詢要先執行,我們才知道 mc.contacts_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語句中~






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