Introduction to SQL — 2

Yunya Hsu
8 min readAug 14, 2021

欄位命名

上一篇提到,SQL有內建的函數 aggregate functions,可以計算最大值 / 最小值 / 平均值 / 加總等。若我們執行該函數,所得的結果,會長什麼樣子呢?

SELECT MAX(budget), MAX(duration)
FROM films;

所得結果如下圖,原本的 films 是沒有自帶 max 欄名的資料,但因為我們執行了 MAX() 函數,所以 SQL 自動把所得結果的欄名命名為 max ;不過,因為兩筆資料都是執行 MAX() 函數,乍看之下難以區分(其實左邊是budget,右邊是duration)。

再看一個例子,上一篇說到,SQL 可以直接針對欄做加減:

SELECT (budget - gross)
FROM films;

所得結果如下,因為我們直接相減,並不是使用函數,所以這次的欄名什麼也沒有:

上面兩種情況,容易在分析資料的時候搞混數據,因此我們需要使用 AS 來命名。原本的命令式可以改寫成以下方式,表頭就出現啦!

SELECT MAX(budget) AS max_budget,
MAX(duration) AS max_duration
FROM films;
SELECT (budget - gross) AS net_profit
FROM films;

利用 SQL 做初步數據分析

在此之前都只是篩選資料,接下來,我們可以針對 SQL 資料做一些簡單的計算及分析。

案例一:假設今天我們有一份叫做 people的資料,這裡面包含了某個社區共一萬名住戶資訊,包含他們的姓名 name、出生日期 birthdate、死亡日期 deathdate。我們試著計算此社區中「已死亡居民的比例」,並把結果的欄位名叫做 percentage_dead

SELECT (COUNT(deathdate) * 1.0 / COUNT(*)) * 100 AS percentage_dead
FROM people;

注意,若只用 (COUNT(deathdate) / COUNT(*)) * 100 ,結果是0。因為 COUNT(deathdate) / COUNT(*) 這個計算式只會取相除後的整數,不含餘數!

案例二:假設有一份叫做 films的資料,這裡面包含了四千多部電影的名字、上映年份、製作國家、電影長度、預算、票房…etc.等資訊。我們想要算出,此份資料中,最舊和最新的電影,差距了多少decades (十年) :

SELECT ( MAX(release_year) - MIN(release_year) ) / 10
AS number_of_decades
FROM films ;

排序 ORDER BY

在 SQL 中選取 / 計算的資料結果,可以依照使用者需求作排序,這時候要出動 ORDER BY 。若沒有定義,SQL 預設為升冪(由小到大,由 A 到 Z ):

SELECT title, release_year
FROM films
ORDER BY release_year;

若要改降冪,則在 ORDER BY 最後加上 DESC

SELECT title, release_year
FROM films
ORDER BY release_year DESC;

我們也可以使用複數個排序,但須注意順序很重要:

SELECT title, release_year, duration
FROM films
ORDER BY release_year, duration;

以下可以看到,電影會優先由 release_year 開始排序,若同一個年份中有2部以上的電影,才會依照 duration 長短排序。此處預設為升冪排序法,故年份及長度皆由小到大。

另外,還記得剛剛有說改為降冪排序法的關鍵字 DESC ,在使用複數排序時,也可以使用的:

SELECT title, release_year, duration
FROM films
ORDER BY release_year, duration DESC;
#以上命令,會依照升冪年份 & 降冪長度排序
SELECT title, release_year, duration
FROM films
ORDER BY release_year DESC, duration DESC;
#年份 & 長度都改為降冪

分類 GROUP BY

用以下例子說明GROUP BY 的使用時機與方式。

一樣使用剛剛的 films 的資料,我們想知道每年上映的電影有多少部?目前我們已知的方法其實可以做到(但比較繁瑣):

SELECT DISTINCT(release_year) 
FROM films ;
#先搞清楚到底有幾個不同的年份
SELECT COUNT(release_year) AS number_1997
FROM films
WHERE release_year=1997 ;
SELECT COUNT(release_year) AS number_1998
FROM films
WHERE release_year=1998 ;
SELECT COUNT(release_year) AS number_1999
FROM films
WHERE release_year=1999 ;
...
...
...

若改使用 GROUP BY ,可簡化成以下方法:

SELECT release_year, count(*) 
FROM films
GROUP BY release_year ;

除了數數量 COUNT(*) ,也可以計算平均值、最大值、最小值等。例如,我們想計算,每一年電影的平均預算是多少:

SELECT release_year AS year_category, AVG(budget) AS average_budgetFROM films
GROUP BY release_year ;

HAVING 用法

前面使用 WHERE 做條件式的時候,都是使用邏輯 (= < > 等等),要注意,不能在 WHERE 裡面搭配aggregate function否則會出現錯誤。

我們想篩選出,每年上映電影大於10部的年份,需使用 HAVING條件式

SELECT release_year, COUNT(*) AS qty
FROM films
GROUP BY release_year
HAVING COUNT(*) > 10;

總複習

請篩選出以下資料:

filme 資料中,上映日期在1990年(不含) 以後,且平均製作預算高6千萬的每一年平均製作預算、平均獲利,且依照平均獲利由高而低排列:

SELECT release_year, AVG(budget) AS avg_budget, AVG(gross) AS avg_gross
FROM films
WHERE release_year > 1990
GROUP BY release_year
HAVING AVG(budget) > 60000000
ORGER BY AVG(gross) DESC;

請篩選出以下資料:

filme 資料中,總共製作10部電影(含)以上的國家,這些國家的平均製作預算及平均獲利。需依國家名(字母)排序,且只顯示前五個國家。

SELECT country, AVG(budget) AS avg_budget, AVG(gross) AS avg_gross, COUNT(*)
FROM films
GROUP BY country
HAVING count(*) > 10
ORDER BY country
LIMIT 5 ;

--

--