close

這是線上平台課程的筆記內容,就是讓自己方便複習用。

老師講課的進度掌握得很好,教得也很淺寫易懂。

線上平台課程內有提供 SQL套件,如果有興趣的朋友一定要去支持老師的課程。

這樣才能取得老師提供的套件包做練習使用。

如果有想要知道老師的課程,再詢問我。


CH8 子查詢

EXISTS

使用他來覆蓋一些使用它的存在。

 

SELECT 欄位

FROM table

WHERE EXISTS(SELECT 欄位 FROM table WHERE 條件)

 

看到EXISTS 就要看一下子查詢的條件是否有滿足。

有滿足的話就會從中提取紀錄。

範例:我想找到19974月份訂購的所有客戶。

這邊我們可以看到我們從customers那拉出了,companyname

SELECT companyname

FROM customers

WHERE EXISTS ()

 

這時候我們剩下的查詢客戶是否有19974月訂單的動作。

EXISTS裡面做。

 

因為這邊的動作橫跨兩張表,所以要使用到JOIN

(SELECT customerid FROM orders

WHERE orders.customerid = customers.customerid

AND orderdate BETWEEN '1997-04-01' AND '1997-04-30');

 

這邊去掉INNER JOIN 直接做JOIN的動作。

透過兩張表的customerid 將兩者JOIN起來。

orders.customerid = customers.customerid

 

合起來

SELECT companyname

FROM customers

WHERE EXISTS

(SELECT customerid FROM orders

WHERE orders.customerid = customers.customerid

AND orderdate BETWEEN '1997-04-01' AND '1997-04-30');

子查詢要JOIN 可以直接把父子查詢的表中的ID對應起來就好。

 

現在來找4月沒有訂單的客戶吧

這時候表示我們要的就是子查詢(EXISTS)的結果的相反。

所以上NOT ,表示不存在的狀況。

SELECT companyname

FROM customers

WHERE NOT EXISTS

(SELECT customerid FROM orders

WHERE orders.customerid = customers.customerid

AND orderdate BETWEEN '1997-04-01' AND '1997-04-30');

 

 

我們來找找看那些產品在1997/04沒有訂單。

1.找產品

2.子查詢找第二需求,符合的條件日期,

要符合的:WHERE EXISTS

不要符合的:WHERE NOT EXISTS

 

SELECT productname

FROM products

WHERE NOT EXISTS ()

 

因為一個問題我們要找的資料只有在order_details裡面才有。

但是我們productJOIN的表只到orders而已。

SELECT

FROM orders

WHERE orders.productid =  products.product.id

 

父子的關係用完之後,只好再用JOIN來完成後面的連結。

SELECT  

FROM orders

INNER JOIN order_details ON order_details.orderid = orders.orderid

WHERE orders.productid =  products.product.id

 

這邊要把要對應的欄位放上去。

因為在products表上面只能認知到productid

所以我們在以查詢內做的事情,是要告訴父查詢。

那些資料是你要的。而那些你要的資料你要能認得才行。

所以我們只能提供productid

 

SELECT productid

FROM orders

INNER JOIN order_details ON order_details.orderid = orders.orderid

WHERE orders.productid = products.product.id

 

加上條件。WHERE的第一步是連接父子。

再來才是條件。接著把我們要的日期欄位放上去

SELECT productid

FROM orders

INNER JOIN order_details ON order_details.orderid = orders.orderid

WHERE orders.productid = products.product.id AND orderdate BETWEEN '1997-04-01' AND '1997-04-30'

 

最後整個語法合起來。

SELECT productname

FROM products

WHERE NOT EXISTS (SELECT productid

FROM order_details

INNER JOIN orders ON orders.orderid = order_details.orderid

WHERE order_details.productid = products.productid

AND orderdate BETWEEN '1997-04-01' AND '1997-04-30');

子查詢找出的productid就是有在那段期間接獲訂單的產品。

返回的productid就是有接獲訂購的產品答案。

如果要相反,就要再加上NOT

 

找到有提供價格超過200元產品的供應商。

1 要顯示的是供應商

SELECT companyname

FROM suppliers

WHERE EXISTS

();

 

2 找尋產品超過200 的廠商supplierid

SELECT supplierid

FROM products

WHERE products.supplierid = suppliers.supplierid

AND unitprice > 200

 

 

3合起來

SELECT companyname

FROM suppliers

WHERE EXISTS

(SELECT productid

FROM products

WHERE products.supplierid = suppliers.supplierid

AND unitprice > 200);

這邊suppliers這張表沒有productid的值。

但這邊會自動對應到那一行當中,有辦法辨識的值當中?

 

現階段比較能理解的還是用 supplierid去返回資料。

如果硬要解釋,就是productid那行的資料,會全部餵回去父查詢那邊。

它可辨別到supplierid = 18的資料,然後帶出我們的值。

 


LAB 想要找到1996/12沒有訂單的供應商

1找供應商。

21996/12沒有訂單的。 反向條件NOT

想到訂單要考慮到,ordersorder_detailsproducts

 

SELECT companyname

FROM suppliers

WHERE NOT EXISTS ()

 

遇到瓶頸,現在連結不回去,所以一定要在JOIN表。

SELECT products.productid FROM products

JOIN oreder_details ON order_details.productid = products.productid

JOIN orders ON orders.orderid = order_details.orderid

WHERE products. supplierid = suppliers.supplierid

AND orderdate BETWEEN '1996-12-01' AND '1996-12-31'

 

這邊透過抓到productid的關鍵,可以抓到supplierid的值。

所以找到那一行的資料,等同於把supplierid拋回去。

 

3合併

SELECT companyname

FROM suppliers

WHERE NOT EXISTS

(SELECT products.productid FROM products

JOIN order_details ON order_details.productid = products.productid

JOIN orders ON orders.orderid = order_details.orderid

WHERE products. supplierid = suppliers.supplierid

AND orderdate BETWEEN '1996-12-01' AND '1996-12-31')

;

 

這邊是這其間有訂單的商品清單

表示沒有的就是沒有被購買的商品清單。

每個商品都會有它的供應商,若沒有產品清單就表示沒有貨的供應商。

 

主要也是因為能夠對應到供應商的就只有product

所以這邊特別把product拉進來。

 

接著要連接到orders.orderdate欄位

products最終目標要連接orders,需要透過order_details來當中介值。

 

order_detailsproductid & orderid可以當雙向連接的值。

之後就可以order_details.orderid去連接orders.orderid

就能取得orders.orderdate欄位

 

SELECT supplierid, companyname

FROM suppliers

WHERE NOT EXISTS

(SELECT products.supplierid FROM products

JOIN order_details ON order_details.productid = products.productid

JOIN orders ON orders.orderid = order_details.orderid

WHERE products. supplierid = suppliers.supplierid

AND orderdate BETWEEN '1996-12-01' AND '1996-12-31')

 


ANY  ALL的使用

SELECT 欄位

FROM table

WHERE 條件 operator ANY

(SELECT 欄位 FROM table WHERE條件)

 

Operator 指的是 = , > , < , >=, <= ,!=

EXISTS 主要就是EXISTS 以及NOT EXISTS,就只有 是,不是而已。

 

找到訂購一件產品的客戶,這些產品單件產品超過50件。

SELECT companyname

FROM customers

WHERE customerid =

(SELECT customerid FROM orders

INNER JOIN order_details ON order_details.orderid = orders.orderid

WHERE quantity >= 50);

如果沒有加上ANY,那他就只能比對一行資料。

如下圖的錯誤。

 

SELECT companyname

FROM customers

WHERE customerid = ANY

(SELECT customerid

FROM orders

INNER JOIN order_details ON order_details.orderid = orders.orderid

WHERE quantity >= 50);

 

LAB 找到訂單中只有一個項目的供應商

Suppliers只有一個order

SELECT companyname

FROM suppliers

WHERE supplierid = ()

 

條件,order只有一個項目。

SELECT supplierid

FROM order_details

WHERE quantity =1

 

要怎麼連接兩張表,這邊可以透過product去做連接。

因為order_details 沒有supplierid。但 products有。

order_details & products有共同的productid可以連接。

 

SELECT supplierid

FROM order_details

INNER JOIN products ON products. productid = order_details. productid

WHERE quantity =1

 

合併

多個條件,加上ANY

SELECT companyname

FROM suppliers

WHERE supplierid = ANY

(SELECT supplierid FROM order_details

INNER JOIN products ON products. productid = order_details. productid

WHERE quantity =1);

 


換成 ALL ,完全一樣的語法。

SELECT 欄位

FROM table

WHERE 條件 operator ALL

(SELECT 欄位 FROM table WHERE條件)

 

Operator 指的是 = , > , < , >=, <= ,!=

 

EXISTS 主要就是EXISTS 以及NOT EXISTS,就只有 是,不是而已。

 

他會選擇所有匹配的紀錄

 

ANY & ALL都是用在子查詢。

兩者最大的區別是,ANY只要一項符合就OKALL 要全部項目符合。

 

找到ORDER_DETAILS內產品金額 高於各項產品統計後最大訂單平均金額的產品

(訂單金額只有order_detail)

可能訂單平均值是10000,但是有其中幾張訂單的平均值遠高於

但我們要顯示productname,所以要先JOIN

 

SELECT productname

FROM products

INNER JOIN order_details ON order_detailers.productid = products.productid

WHERE order_details.unitprice*quantity > ALL

()

 

子查詢條件

SELECT AVG(order_details.unitprice*quantity)

FROM orders_details

GROUP BY productid

 

分組處理一下,依照productid來分類。

這邊的group by 會依照productid區分組別,。

 

合併

SELECT productname

FROM products

INNER JOIN order_details ON order_details.productid = products.productid

WHERE order_details.unitprice*quantity > ALL

(SELECT AVG(order_details.unitprice*quantity)

FROM order_details

GROUP BY productid );

 

ANY只要這邊的產品金額大於任意一個產品平均值就會顯示。

ALL表示,這邊的產品金額要大於所有商品內最大的平均值金額。

 

例如:

子查詢內找到 產品13號是最大的平均值金額。假設10000

那我父查詢這邊就是我商品的金額要大於這個產品13的最大金額才會顯示。

 

SELECT productname, order_details.unitprice, order_details.quantity

FROM products

INNER JOIN order_details ON order_details.productid = products.productid

WHERE order_details.unitprice*quantity > ALL

(SELECT AVG(order_details.unitprice*quantity)

FROM order_details

GROUP BY productid );

 

這邊會發現有多個訂單的產品賣出金額,超過平均值。

所以用ALL在比較的時候,產品賣出的金額大於所有平均值的。

 

訂單有時候的單價會不一樣。

這邊會算出產品1 每張單加起來的總額的平均值。

這邊可以看到產品1的單價是18元。

這邊可以看到許多單超過375元。

表示群組抓出來的確實是平均值。

 

最後因為重複的品項太多。

我們用DISTINCT來把一樣的篩選掉。

 

SELECT DISTINCT productname

FROM products

INNER JOIN order_details ON order_details.productid = products.productid

WHERE order_details.unitprice*quantity > ALL

(SELECT AVG(order_details.unitprice*quantity)

FROM order_details

GROUP BY productid );

這邊換成ANY就是不一樣的結果

只要這邊的產品金額大於任意一個產品平均值就會顯示。

 

LAB 找到一個客戶,購買的東西價格高於平均值。

SELECT DISTINCT companyname

FROM customers

INNER JOIN orders ON customers.customerid = orders.customerid

INNER JOIN order_details ON order_details.orderid = orders.orderid

WHERE order_details.unitprice*quantity > ALL

(SELECT AVG(order_details.unitprice*quantity)

FROM order_details

JOIN orders ON order_details.orderid = orders.orderid

GROUP BY customerid );

 

這邊是要找客戶,所以先找customers表。

因為最後是要算出購買金額的平均值,

必須要有unitprice & quantity的值。

這兩個的值必須抓order_details表。 這其中透過orders做橋梁連接。

SELECT DISTINCT companyname

FROM customers

INNER JOIN orders ON customers.customerid = orders. customerid

INNER JOIN order_details ON order_details.order.id = orders.orderid

WHERE order_details.unitprice*quantity > ALL

 

子查詢的資料

要從unitprice & quantity找出平均值。

所以採用order_detail的表。

但因為要以customerid 作為分類的條件(題目是以客戶為主,所以要先分出來)

所以把orders這張表帶進來。

 

SELECT AVG(order_details.unitprice*quantity)

FROM order_details

JOIN orders ON order_details.order.id = orders.orderid

GROUP BY customerid

 


ANY ALL的比較。

 

這邊用學生來比較比較簡單。

例如說: A VS B班,查詢A班年紀大於B班的。

ALL來說。查詢A班當中,年齡大於B班所有人的人。

ANY來說。查詢A班當中,年齡大於B班任意一個人的人。

 

上面有用到金額的平均值來比較。

產品金額 VS 產品的平均值

 

ALL 來說,產品金額,大於所有產品平均值的。

SELECT * FROM TABEL WHERE MONEY > ALL (SELECT MONEY FROM TABLE)

等於

SELECT * FROM TABEL WHERE MONEY > (SELECT MAX(MONEY) FROM TABLE)

 

ANY來說,產品金額,大於任意一個平均值的。

SELECT * FROM TABEL WHERE MONEY > ANY (SELECT MONEY FROM TABLE)

等於

SELECT * FROM TABEL WHERE MONEY > (SELECT MIN(MONEY) FROM TABLE)

 

SELECT * FROM TABEL WHERE MONEY = ANY (SELECT MONEY FROM TABLE)

等於

SELECT * FROM TABEL WHERE MONEY IN (SELECT MONEY) FROM TABLE)

 


IN 的子查詢。

SELECT 欄位

FROM table

WHERE 欄位 IN (SELECT statement)

選擇的值,必須與IN裡面的匹配。

主要就是比較裡面有沒有相同的值。

 

我們將找到與供應商在同一個國家地區的客戶。

SELECT companyname

FROM customers

WHERE country IN (SELECT country FROM suppliers);

他會找到兩邊一樣的值,然後拉出來。

LAB 找到與供應商在同CITY的客戶。

SELECT companyname

FROM suppliers

WHERE city IN

(SELECT city FROM customer);

 

這邊會先在IN裡面拉出city欄位。

讓他作為條件,然後去比對suppliers內有沒有相同CITYsuppliers

 

他就是一層一層迴圈式的去找,

最終找到五家客戶&供應商在同一個CITY的資料。

<本篇完>


第一篇:  IT讀書室-SQL語法學習- postgre安裝與匯入

第二篇:  IT讀書室-SQL語法學習- SELECT查詢

第三篇:  IT讀書室-SQL語法學習- WHERE條件

第四篇:  IT讀書室-SQL語法學習- 中間的SELECT語句

 


如果筆記造成任何法律或者侵權的問題,作者會立即將筆記下架。

 

 

 

 

arrow
arrow
    全站熱搜

    IT001 發表在 痞客邦 留言(0) 人氣()