go where 不等於_on和where的過濾
阿新 • • 發佈:2021-01-29
技術標籤:go where 不等於
之前一直沒在意,直到這個習題才發現掉坑了
表DistrictProducts
/* 練習題1-2-2:分地區排序 */ CREATE TABLE DistrictProducts (district VARCHAR(16) NOT NULL, name VARCHAR(16) NOT NULL, price INTEGER NOT NULL, PRIMARY KEY(district, name, price)); INSERT INTO DistrictProducts VALUES('東北', '橘子', 100); INSERT INTO DistrictProducts VALUES('東北', '蘋果', 50); INSERT INTO DistrictProducts VALUES('東北', '葡萄', 50); INSERT INTO DistrictProducts VALUES('東北', '檸檬', 30); INSERT INTO DistrictProducts VALUES('關東', '檸檬', 100); INSERT INTO DistrictProducts VALUES('關東', '菠蘿', 100); INSERT INTO DistrictProducts VALUES('關東', '蘋果', 100); INSERT INTO DistrictProducts VALUES('關東', '葡萄', 70); INSERT INTO DistrictProducts VALUES('關西', '檸檬', 70); INSERT INTO DistrictProducts VALUES('關西', '西瓜', 30); INSERT INTO DistrictProducts VALUES('關西', '蘋果', 20);
要求輸出
作者提示三種解
- rank
#直接用rank來做
select district , name ,price , rank() over(PARTITION BY district order by price desc ) rank_1
from DistrictProducts
order by district ,price desc
2. 子查詢方式
#子查詢方式,作者也寫過 select district , name ,price , ( select count(*)+1 from DistrictProducts d2 where d2.district = d1.district and d2.price > d1.price ) rank_1 from DistrictProducts d1 order by d1.district , price desc ;
3. 自連線方式(作者提供·)
select d1.district ,d1.name, MAX(d1.price) AS price, COUNT(d2.name) +1 AS rank_1 from DistrictProducts d1 left join DistrictProducts d2 on d1.district = d2.district and d1.price < d2.price GROUP BY d1.district, d1.name order by d1.district , d1.price desc ;
發現自己難以得到正確輸出的原因在於對ON和WHERE中相同過濾條件的結果認知不足
舉例如下:
集合1(記錄數為16)
select d1.district ,d1.name,
d1.*,d2.*
from
DistrictProducts d1
left join DistrictProducts d2
on d1.district = d2.district
and d1.price < d2.price
集合2(記錄數為11)
select d1.district ,d1.name,
d1.*,d2.*
from
DistrictProducts d1
left join DistrictProducts d2
on d1.district = d2.district
where d1.price < d2.price
兩個集合完全不一致!
以例子中的表而言,
DistrictProducts d1
left join DistrictProducts d2
on d1.district = d2.district
產生了41條記錄(計算如下)
select sum(count_pow)
from
(
select district,pow(count(*),2) count_pow
from
DistrictProducts d1
group by district
)r
隨後這41條記錄由於ON和WHERE過濾條件的緣故產生差異
LEFT JOIN ON的形式決定了左表每條記錄出現次數有且大於等於一次,如右表有對應於左表的記錄,則對應的左表返回右表對應的記錄,反之,則返回左表。
WHERE則是在這41條記錄的基礎上進行了布林判定,即返回TRUE的記錄。
故在類似的過濾條件下, LEFT JOIN ON的記錄數>=WHERE的記錄數。