1. 程式人生 > 其它 >【SQL學習筆記】《SQL進階教程》1.2

【SQL學習筆記】《SQL進階教程》1.2

技術標籤:SQLmysql

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