【SQL學習筆記】《SQL進階教程》1.2
阿新 • • 發佈:2021-01-23
1-2自連線的用法
自連線+非等值連線
自連線+GROUP BY = 遞迴集合
表是行的集合,面向集合
開銷較大
唯二重要的方法
CASE 自連線
SQL語言 : 面向集合的特性
可重排列、排列、組合
有序對<>、無序對{}
--獲取可重排列(交叉連線 笛卡爾積) 3*3
SELECT P1.name AS name_1, P2.name AS name_2
FROM Products P1, Product P2;
--獲取排列 A32 = 3*2
SELECT P1.name AS name_1, P2.name AS name_2
FROM Products P1, Products P2
WHERE P1.name <> P2.name;
--獲取組合C32 = 2*3 / 2
SELECT P1.name AS name_1, P2.name AS name_2
FROM Products P1, Products P2
WHERE P1.name > P2.name;
--獲取組合: 擴充套件程3列
SELECT P1.name AS name_1, P2.name AS name_2, P3.name AS name_3
FROM Products P1, Products P2, Products AS P3
WHERE P1.name > P2.name
AND P2.name > P3.name;
刪除重複行
可用的行id僅有Oracle和postgresql可以使用、且pgsl需要在建表是指定with oids
--關聯子查詢:對兩個擁有相同資料的集和進行的關聯操作
DELETE FROM Products P1
WHERE rowid < ( SELECT MAX(P2.rowid))
FROM Products P2
WHERE P1.name = P2.name
AND P1.price = P2.price ) ;
--集合是SQL唯一可以處理的資料結構
--刪除重複行(2):非等值連線 **更常用**
DELETE FROM Products P1
WHERE EXISTS ( SELECT *
FROM Products P2
WHERE P1.name = P2.name
AND P1.price = P2.price
AND P1.rowid < P2.rowid ) ;
查詢區域性不一致的列
--查詢同一家人住址不同
--尋找價格相等的商品組合(+ DISTINCT 避免出現重複行)
--自連線 + 非等值連線
SELECT DISTINCT A1.name, A1.address
FROM Addresses A1, Addresses A2
WHERE A1.family_id = A2.family_id
AND A1.address <> A2.address ;
-- 用於查找價格相等但商品名稱不同的記錄的 SQL 語句(DISTINCT)
SELECT DISTINCT P1.name, P1.price
FROM Products P1, Products P2
WHERE P1.price = P2.price
AND P1.name <> P2.name;
--關聯子查詢方法(作業)
SELECT P1.name, P1.price
FROM Products AS P1
WHERE P1.name <> ( SELECT P2.name
FROM Products AS P2
WHERE P1.price = P2.price)
排序
跳過之後的位次
不跳過之後的位次
--視窗函式
SELECT name, price,
--跳過之後的位次,123336
RANK() OVER (ORDER BY price DESC) AS rank_1
--不跳過之後的位次,123334
DENSE_RANK() OVER (ORDER BY price DESC) AS rank_2
FROM Products
--非等值自連線
--有幾個比自己大的再加一就是自己的排序
--排序從 1 開始。如果已出現相同位次,則跳過之後的位次
--去掉 +1 則從0排序;COUNT(DISTINCT P2.price),則不跳過之後的位次。
SELECT P1.name, P1.price,
(SELECT COUNT(P2.price)
FROM Products P2
WHERE P2.price > P1.price) + 1 AS rank_1
FROM Products P1
ORDER BY rank_1;
--排序:使用自連線
SELECT P1.name,
MAX(P1.price) AS price,
COUNT(P2.name) +1 AS rank_1
FROM Products P1 LEFT OUTER JOIN Products P2
ON P1.price < P2.price
GROUP BY P1.name
ORDER BY rank_1;
--排序:使用內連線,結果沒有第一名
SELECT P1.name,
MAX(P1.price) AS price,
COUNT(P2.name) +1 AS rank_1
FROM Products P1 INNER JOIN Products P2
ON P1.price < P2.price
GROUP BY P1.name
ORDER BY rank_1;
習題1-2-1可重組合
SELECT P1.name AS name_1, P2.name AS name_2
FROM Products P1 Products P2
WHERE P1.name >= P2.name;
1-2-2 分地區排序
SELECT district, name, price,
RANK OVER(PARTITION BY district ORDER BY price DESC) AS rank_1
FROM DistrictProducts;
--關聯子查詢
SELECT P1.district, P1.name,
P1.price,
(SELECT COUNT(P2.price)
FROM DistrictProducts P2
WHERE P1.district = P2.district /* 在同一個地區內進行比較 */
AND P2.price > P1.price) + 1 AS rank_1
FROM DistrictProducts P1;
/* 練習題1-2-2:自連線 */
SELECT P1.district, P1.name,
MAX(P1.price) AS price,
COUNT(P2.name) +1 AS rank_1
FROM DistrictProducts P1 LEFT OUTER JOIN DistrictProducts P2
ON P1.district = P2.district
AND P1.price < P2.price
GROUP BY P1.district, P1.name;
更新位次
/* 練習題1-2-3:更新位次 */--關聯子查詢
UPDATE DistrictProducts2 P1
SET ranking = (SELECT COUNT(P2.price) + 1
FROM DistrictProducts2 P2
WHERE P1.district = P2.district
AND P2.price > P1.price);
--自連線
UPDATE DistrictProducts2
SET ranking =
(SELECT P1.ranking
FROM (SELECT district , name ,
RANK() OVER(PARTITION BY district
ORDER BY price DESC) AS ranking
FROM DistrictProducts2) P1
WHERE P1.district = DistrictProducts2.district
AND P1.name = DistrictProducts2.name);