使用SQL獲取不同類型的類型的特定數據

這裏有一個常見的SQL問題: 如何找到當前的每個程序的最新的日誌? 如何從不同類別中找到最常使用的數據?等等. 通常情況這類問題可以被簡化爲"從不同的類別中選取特定的數據".
這裏假設數據庫的表結構及其數據如下所示:

+--------+------------+-------+
| type   | variety    | price |
+--------+------------+-------+
| apple  | gala       |  2.79 | 
| apple  | fuji       |  0.24 | 
| apple  | limbertwig |  2.87 | 
| orange | valencia   |  3.59 | 
| orange | navel      |  9.36 | 
| pear   | bradford   |  6.05 | 
| pear   | bartlett   |  2.14 | 
| cherry | bing       |  2.55 | 
| cherry | chelan     |  6.33 | 
+--------+------------+-------+

查詢每個類別的最小的值

這裏我們先把我們所期望的結果放在這裏

+--------+----------+-------+
| type   | variety  | price |
+--------+----------+-------+
| apple  | fuji     |  0.24 | 
| orange | valencia |  3.59 | 
| pear   | bartlett |  2.14 | 
| cherry | bing     |  2.55 | 

當然了,要得到這問題的答案有很多種.這裏用兩種來解釋一下.
一種常見的方式是self-join,

  • 首先根據不同的類別進行分組,
select type, min(price) as minprice
from fruits
group by type;
+--------+----------+
| type   | minprice |
+--------+----------+
| apple  |     0.24 | 
| cherry |     2.55 | 
| orange |     3.59 | 
| pear   |     2.14 | 
+--------+----------+
  • 第二部是將查詢得到的數據重新連接到相同的table中;因爲第一部分的查詢已經分組了,因此需要將其放在子查詢中並將其連接到table中
select f.type, f.variety, f.price
from (
   select type, min(price) as minprice
   from fruits group by type
) as x inner join fruits as f on f.type = x.type and f.price = x.minprice;
+--------+----------+-------+
| type   | variety  | price |
+--------+----------+-------+
| apple  | fuji     |  0.24 | 
| cherry | bing     |  2.55 | 
| orange | valencia |  3.59 | 
| pear   | bartlett |  2.14 | 

這裏還有一種方式是使用相關子查詢.從效率上將可能有第一點,但是她更加清晰.

select type, variety, price
from fruits
where price = (select min(price) from fruits as f where f.type = fruits.type);
+--------+----------+-------+
| type   | variety  | price |
+--------+----------+-------+
| apple  | fuji     |  0.24 | 
| orange | valencia |  3.59 | 
| pear   | bartlett |  2.14 | 
| cherry | bing     |  2.55 | 

通過了子查詢\相關子查詢我們可以比較輕鬆的從大量數據中獲取每一種類的數據.接下來我們更進一步

獲取每種數據的TOP N數據

通常情況下各種數據庫都提供了諸如MAX() MIN()這樣的聚合函數來返回單獨的一行數據.但是我們這裏需要返回多條數據.先來看看第一種實現:

select type, variety, price
from fruits
where price = (select min(price) from fruits as f where f.type = fruits.type)
   or price = (select min(price) from fruits as f where f.type = fruits.type
      and price > (select min(price) from fruits as f2 where f2.type = fruits.type));
+--------+----------+-------+
| type   | variety  | price |
+--------+----------+-------+
| apple  | gala     |  2.79 | 
| apple  | fuji     |  0.24 | 
| orange | valencia |  3.59 | 
| orange | navel    |  9.36 | 
| pear   | bradford |  6.05 | 
| pear   | bartlett |  2.14 | 
| cherry | bing     |  2.55 | 
| cherry | chelan   |  6.33 | 
+--------+----------+-------+

可以看到其實思路很簡單,這裏用SQL的僞代碼來表示一下其實現方式

select type, variety, price
from fruits
where price = 價錢最低的 OR
  price = 價錢最低的 AND price > 價錢最低的

這種方式可以實現,但是可拓展性比較差.如果現在需要查詢TOP 3,TOP 4 怎麼辦?這裏還有一種方式實現查詢TOP 2
TOP 2 其實質就是 : 價格小於等於第二個便宜的產品.

select type, variety, price
from fruits
where (
   select count(*) from fruits as f
   where f.type = fruits.type and f.price <= fruits.price
) <= 2;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章