操作陣列不只是建立跟存資料而已,很多時候你會需要把單一元素抓出來,或是分析裡面的內容。PostgreSQL 內建了幾個 function 來做這些事,下面我們一個一個來看。
unnest() function:把陣列拆開
unnest() 這個 function 就是把一個陣列拆成一堆 row,每個元素變成一行。這在你想把陣列內容當成 table 來操作時超級有用。
範例 1:簡單拆陣列
假設我們有一個存放學院名稱的陣列:
SELECT ARRAY['資訊學', '數學', '物理'] AS 學院們;
現在要把每個元素都變成一行,用 unnest():
SELECT unnest(ARRAY['資訊學', '數學', '物理']) AS 學院;
結果:
| 學院 |
|---|
| 資訊學 |
| 數學 |
| 物理 |
範例 2:在 table 裡拆陣列
假設我們有一個 courses table:
CREATE TABLE courses (
course_id SERIAL PRIMARY KEY,
course_name TEXT,
tags TEXT[]
);
INSERT INTO courses (course_name, tags)
VALUES
('演算法', ARRAY['程式設計', '資訊學']),
('線性代數', ARRAY['數學', '代數']),
('物理基礎', ARRAY['物理', '一般']);
現在我們要把所有 tag 從陣列抓出來:
SELECT course_name, unnest(tags) AS tag
FROM courses;
結果:
| course_name | tag |
|---|---|
| 演算法 | 程式設計 |
| 演算法 | 資訊學 |
| 線性代數 | 數學 |
| 線性代數 | 代數 |
| 物理基礎 | 物理 |
| 物理基礎 | 一般 |
你可以看到,陣列裡的每個元素都變成 table 裡的一行。
array_length() function:算陣列長度
第二個很重要的 function 是 array_length(),它會回傳你指定維度的陣列長度(也就是元素個數)。
範例 1:一維陣列的元素數量
來看一個陣列:
SELECT ARRAY['蘋果', '香蕉', '橘子'] AS 水果們;
如果你想知道這個陣列有幾個水果:
SELECT array_length(ARRAY['蘋果', '香蕉', '橘子'], 1) AS 長度;
結果:
| 長度 |
|---|
| 3 |
這裡 1 代表你要查第幾個維度。PostgreSQL 的陣列可以有多維(像是二維陣列),但這裡我們先不討論。
範例 2:查 table 裡陣列的元素數量
來看每個課程有幾個 tag:
SELECT course_name, array_length(tags, 1) AS 標籤數量
FROM courses;
結果:
| course_name | 標籤數量 |
|---|---|
| 演算法 | 2 |
| 線性代數 | 2 |
| 物理基礎 | 2 |
這 function 就直接告訴你:「欸,這裡有兩個元素!」這樣分析資料就方便多了。
array_position() function:找陣列裡的值
現在,假設你要在陣列裡找某個特定元素。array_position() 就派上用場了:它會回傳第一次出現這個元素的位置。
範例 1:找元素
假設有個陣列:
SELECT ARRAY['紅色', '藍色', '綠色', '黃色'] AS 顏色們;
來找一下「藍色」的位置:
SELECT array_position(ARRAY['紅色', '藍色', '綠色', '黃色'], '藍色') AS 位置;
結果:
| 位置 |
|---|
| 2 |
如果找不到這個元素,function 會回傳 NULL。來試試看:
SELECT array_position(ARRAY['紅色', '藍色', '綠色', '黃色'], '黑色') AS 位置;
結果:
| 位置 |
|---|
| NULL |
範例 2:在 table 陣列裡找元素
你想知道哪個課程有「資訊學」這個 tag。先找出對應的 row:
SELECT course_name, array_position(tags, '資訊學') AS 位置
FROM courses;
結果:
| course_name | 位置 |
|---|---|
| 演算法 | 2 |
| 線性代數 | NULL |
| 物理基礎 | NULL |
再加個條件,只留下有這個 tag 的 row:
SELECT course_name
FROM courses
WHERE array_position(tags, '資訊學') IS NOT NULL;
結果:
| course_name |
|---|
| 演算法 |
array_position() 讓你可以很快在陣列裡找到資料,這 function 在 PostgreSQL 處理陣列時超級重要。
function 的實戰應用
unnest()— 用來把陣列轉成 row。這對資料分析、報表、處理 tag 都很重要。array_length()— 超適合拿來檢查陣列長度。像是資料驗證時,可以檢查陣列是不是空的。array_position()— 找元素超方便,不管是商品分類、學生參加的專案,還是描述裡的關鍵字都能用。
用 function 時常見的錯誤
unnest()如果同時對多個 column 的陣列用,row 數可能會變兩倍。這時可以加JOIN LATERAL或CROSS JOIN來解決,但要小心用。array_length()對空陣列會回傳NULL。如果你的陣列可能是空的,記得要另外檢查。array_position()找不到元素時會回傳NULL,所以在 filter 時最好 always 加IS NOT NULL。
真實專案裡的例子
PostgreSQL 的陣列不是只在理論上好用,實際專案也很強大。像你寫 blog,每篇文章有一堆 tag,用陣列存就能很快 filter 出同主題的文章,甚至可以做熱門分類排行榜。
又或者你要分析使用者行為,他們可能會選好幾個有興趣的課程或商品,這些偏好用陣列存起來,處理起來也很方便。
還有,陣列也能幫你驗證資料:用 array_length() 可以限制元素數量,比如不讓使用者選超過五個選項。
GO TO FULL VERSION