掌握多層嵌套 JSONB 的查詢技巧:從入門到進階

更新日期: 2025 年 3 月 25 日

在 PostgreSQL 的資料世界裡,JSONB 是個非常靈活而強大的資料類型。

它能夠儲存結構化卻不固定格式的資料,因此廣泛被用在 API response、NoSQL 式的資料欄位、甚至是活動紀錄等場景。

但這份自由也有代價:當資料開始出現巢狀結構,甚至巢中有陣列、陣列中又有物件時,查詢寫起來往往讓人懷疑人生。

這篇文章會從最基礎的概念出發,一步一步帶你掌握查詢多層嵌套 JSONB 的核心技巧,不只學語法,更建立你的「資料結構處理思維」。


JSONB 基礎複習:你真的理解 JSONB 嗎?

在進入查詢技巧之前,我們先回到最基本的問題——什麼是 JSON?什麼又是 JSONB?它們有什麼不同?

JSON vs JSONB:看似相同,實則大不同

PostgreSQL 提供兩種格式來儲存 JSON 資料:JSONJSONB

雖然兩者都可以儲存結構化的資料,但底層運作方式大不相同,這也會影響你的查詢效率與操作彈性。

類型說明
JSON以純文字(text)格式儲存資料。資料會以原始樣貌保留,包括欄位順序與空格,優點是符合 JSON 標準,但每次查詢時都需要即時解析資料,效能較差。
JSONBBinary(位元)格式儲存資料。會先解析 JSON 結構再儲存,因此欄位順序會被移除,但換來的是更快的查詢速度,並且支援索引操作。非常適合在資料表中經常需要查詢、篩選的場景。

🔍 什麼時候該用哪一個?

  • 如果你只想「原樣儲存 JSON 資料,不查它」,可以用 JSON
  • 如果你想「查詢 JSON 裡的欄位、值,甚至做條件篩選」,就用 JSONB

簡單一句話: JSON 是原始資料格式,JSONB 是為了查資料而生的進化版本。

巢狀結構為何常見?

如果你之前有處理過前端 API 或 NoSQL 文件資料格式,就會發現 JSON 資料幾乎都是巢狀結構。

這並不是故意為難資料庫設計師,而是因為這樣的結構更貼近「真實世界的資料邏輯」。

來看看一個模擬的 JSON 資料,描述一個使用者與他發表的文章:

{
  "user": {
    "id": 1,
    "name": "Alice",
    "posts": [
      {"title": "第一篇", "likes": 10},
      {"title": "第二篇", "likes": 5}
    ]
  }
}

這種資料設計為什麼實用?讓我們一層一層拆解來看:

結構層級描述
user是一個物件(Object),代表一位使用者
user.id 和 user.name是使用者的基本資料
user.posts是一個陣列,裡面放著使用者發表的所有貼文
posts[0]、posts[1]每篇貼文又是獨立的物件,內含 title 與 likes 欄位

這樣的巢狀結構有幾個好處:

  1. 直觀且符合邏輯:貼文是屬於使用者的,所以放在 user 裡很自然。
  2. 彈性高:可以放任意多的貼文,不需要修改資料表 schema。
  3. 節省關聯查詢:不需要 JOIN 多個表格就能一次取得完整資訊。

巢狀結構會有哪些型態?

巢狀不只一種,有幾種常見的搭配方式:

  • 物件中嵌套物件(Object in Object)
  • 物件中嵌套陣列(Array in Object)
  • 陣列中又是物件(Object in Array)
  • 陣列中嵌套陣列(Array in Array,較少見)

用圖解的話,大概長這樣:

{
  A: {
    B: [ 
      { C: 123 }, 
      { C: 456 } 
    ]
  }
}
  • A 是外層物件
  • B 是物件內的陣列
  • 陣列裡每個元素又是物件

巢狀結構的代價是什麼?

當然,好處多,不代表沒有代價。巢狀資料結構的缺點就是——查詢起來麻煩,語法也容易變長且複雜

而這正是這篇文章接下來要解決的問題:如何用最清晰的方式,查詢這些巢狀 JSONB 結構?

所以別擔心巢太深,只要你跟著學會正確的操作方式,處理這種資料就像剝洋蔥一樣,一層一層來,清楚又有條理!


基本操作語法:->->> 怎麼用?

在 PostgreSQL 操作 JSONB 資料時,最基本、最常見的兩個運算子就是:

  • ->:取出 JSON 格式的值,結果仍保留為 JSON
  • ->>:取出 文字格式的值,結果為純文字(text)

這兩個符號的差異是初學者的第一個關卡,但一旦理解,你就能靈活存取任何一層的資料。

使用 ->:取出 JSON 格式的欄位值(仍為 JSON)

當你使用 -> 時,PostgreSQL 會回傳資料中指定欄位的值,但保留原本的 JSON 格式,也就是說——你拿到的仍然是一段 JSON,而不是單純的文字。

這個語法特別適合,在你還需要繼續往下存取巢狀欄位,或者打算用其他 JSON 函數處理時使用。

🧪 查詢範例

假設我們有一筆使用者資料如下,儲存在 users 資料表的 data 欄位中:

{
  "user": {
    "id": 1,
    "name": "Alice",
    "posts": [
      { "title": "第一篇", "likes": 10 },
      { "title": "第二篇", "likes": 5 }
    ]
  }
}

若你想取出整個 user 區塊,可以這樣寫:

SELECT data->'user' AS user_object
FROM users;

📌 查詢結果會是:

{
  "id": 1,
  "name": "Alice",
  "posts": [
    { "title": "第一篇", "likes": 10 },
    { "title": "第二篇", "likes": 5 }
  ]
}

這段結果仍然是 JSON 格式,你可以用來:

  • 再往下存取某個欄位(例如 ->'name'
  • 交給其他 JSON 處理函式(如 jsonb_array_elements()
  • 組裝成新的 JSON 結構

❗️限制:不能直接比較或排序

因為結果是 JSON 而非文字,下面這種寫法會報錯:

-- 錯誤!不能對 JSON 直接做排序
SELECT * FROM users
ORDER BY data->'user'->'name';

你會看到錯誤訊息類似:

ERROR:  could not identify an ordering operator for type jsonb

所以,如果你想進行比較、排序或文字操作,就得改用 ->>

使用 ->>:取出文字格式的欄位值(轉成 text)

當你使用 ->> 時,PostgreSQL 會幫你把目標欄位的值取出後,轉成文字格式(text),這樣就可以進行字串比對、排序或套用文字函數。

這是你在日常查詢中最常用的格式,特別是當你需要進行條件篩選或展示資料時。

🧪 查詢範例

假設你只想取得使用者名稱(name 欄位的值),可以這樣寫:

SELECT data->'user'->>'name' AS username
FROM users;

📌 查詢結果:

username
Alice

這裡的 data->'user'->>'name' 意思是:

  • 先從 data 中取出 user 這個欄位(為 JSON 格式)
  • 接著從 user 裡面取出 name 欄位,並用 ->> 將它轉為文字格式

✅ 文字格式的好處

使用 ->> 取出的資料是文字,你可以:

1️⃣ 加上 WHERE 條件

SELECT *
FROM users
WHERE data->'user'->>'name' = 'Alice';

2️⃣ 做排序

SELECT data->'user'->>'name' AS username
FROM users
ORDER BY username ASC;

3️⃣ 使用文字函式處理

SELECT 
  data->'user'->>'name' AS username,
  LENGTH(data->'user'->>'name') AS name_length,
  LOWER(data->'user'->>'name') AS lowercase_name
FROM users;

常見誤解:我可不可以只用一種就好?

這是很多初學者的疑問,但答案是——不行,因為兩者用途不同

情境應該使用
還要繼續往下一層取值(巢狀結構)->
要比對值、排序、當作文字處理->>
要把資料餵給 jsonb_array_elements() 等函式->

正確地交替使用 ->->>,才是查詢 JSONB 的關鍵技巧。

🧩 小提醒:兩者可以混搭使用

你可以在查詢中同時使用 ->->>,例如:

SELECT
  data->'user'->>'name' AS username,
  data->'user'->'posts' AS user_posts
FROM users;

這會同時取出:

  • 使用者名稱(文字格式)
  • 使用者貼文列表(JSON 陣列)

非常適合在需要顯示資訊 + 保留原始結構時使用。

🧠 小技巧:你其實在用「鏈結存取」

當你寫出這樣的語法時:

data->'user'->'posts'->0->>'title'

你其實在做「逐層存取」:

  1. data->'user':取得使用者物件
  2. ->'posts':取得貼文陣列
  3. ->0:取得陣列中的第一篇貼文(索引從 0 開始)
  4. ->>'title':從該貼文中取出 title 欄位,並轉為文字

這樣的寫法其實是「一路往下挖」,類似你在 JavaScript 中這樣取值:

data.user.posts[0].title

⚠️ 為什麼這種寫法不夠好?

雖然這樣寫可以正常執行,但它有幾個缺點:

  • 可讀性差:看不出哪一層是物件、哪一層是陣列
  • 維護困難:資料結構改變時容易錯位
  • 無法應對多筆資料:只能拿到「一筆」(例如 posts[0]),但現實情況你很可能想查出「所有貼文」

因此,如果你想要處理的是陣列(像是所有貼文),就該學會更標準的方式來展開這些資料,這正是我們下一章會介紹的重點——jsonb_array_elements()


認識 ->0:巢狀結構裡的第一堂課

在處理 JSONB 巢狀資料時,你很快就會遇到一個語法:->0

這個語法的意思是:從 JSON 陣列中,取出第 0 筆(也就是第一筆)資料

就像 JavaScript 裡的 array[0] 一樣,索引從 0 開始。

不過,這個語法有個關鍵前提只有「陣列」才可以使用索引 ->0。如果你不小心對一個「物件」使用 ->0,就會報錯。

什麼是陣列?什麼是物件?

我們來看一段實際的 JSON 資料結構(儲存在 users 資料表的 data 欄位中):

{
  "user": {
    "id": 1,
    "name": "Alice",
    "posts": [
      { "title": "第一篇", "likes": 10 },
      { "title": "第二篇", "likes": 5 }
    ]
  }
}

結構說明:

欄位路徑類型說明
dataObject最外層物件
data->'user'Object使用者資訊
data->'user'->'posts'Array貼文陣列,每篇貼文是物件

✅ 正確使用 ->0 的範例:取出陣列中的第一筆資料

因為 posts 是一個陣列,所以你可以使用索引來存取裡面的貼文。例如,取出第一篇貼文的標題:

SELECT data->'user'->'posts'->0->>'title' AS first_post_title
FROM users;

操作順序解析:

  1. data->'user':取得使用者物件(Object)
  2. ->'posts':進入 posts 陣列
  3. ->0:取得陣列中的第一筆資料(第一篇貼文)
  4. ->>'title':從該貼文物件中取出標題,並轉為文字格式

📌 查詢結果範例如下:

first_post_title
第一篇

❌ 常見錯誤:「我以為 ->0 可以用在任何東西」

你可能會想寫:

SELECT data->'user'->0->>'name' AS name
FROM users;

這會報錯,因為 data->'user' 是一個 物件(object),你不能對物件使用索引 ->0。只有陣列才可以這樣取值。

PostgreSQL 會回傳類似以下錯誤訊息:

ERROR: cannot extract array element from a non-array

判斷型別後決定用法

簡單整理如下:

資料類型正確存取方式
Object(物件)使用 key 名稱:->'key'
Array(陣列)使用索引值:->0、->1

你可以透過 jsonb_typeof() 函式來確認一段 JSON 是不是陣列:

SELECT jsonb_typeof(data->'user'->'posts') AS type
FROM users;
-- 結果會是:array

⚠️ 限制:->0 只能取單筆,無法查多筆或做統計

雖然 ->0 很直觀,能快速抓第一筆資料,但它的用途其實非常有限。舉例來說:

  • 你只能取得一筆貼文
  • 你沒辦法用它查出所有貼文
  • 你也無法對貼文做加總、排序、篩選等操作

為什麼我們需要展開陣列?

當你面對一個像這樣的貼文陣列:

"posts": [
  { "title": "第一篇", "likes": 10 },
  { "title": "第二篇", "likes": 5 }
]

你可能會想:

  • 我要統計每篇貼文的按讚數
  • 我要列出所有貼文標題
  • 我要找出按讚最多的那一篇

這時候,你就不能只靠 ->0。因為:

❗️ ->0 是「定點取值」

只能拿第一篇,沒有辦法變出 2、3、4… 或 10 篇資料。

如果你有一位使用者有 10 篇貼文,你不會想手動寫 ->0->9 吧?這時候,就必須用 PostgreSQL 提供的強大函式 —— jsonb_array_elements(),來展開整個貼文陣列。

這也正是我們下一節要介紹的重點。

jsonb_array_elements() 是「展開整包」

它能把整個陣列展開,每個元素都變成一筆獨立資料列

這樣你才能對「每篇貼文」進行分析,而不只是看到第一篇。

這就是處理巢狀陣列結構的真正起點:你不只是讀資料,而是要讓資料「攤平」才能好好查詢。


jsonb_array_elements():從陣列變資料列的關鍵轉換

它的用途是什麼?

當你有一個 JSON 陣列,像這樣:

"posts": [
  { "title": "第一篇", "likes": 10 },
  { "title": "第二篇", "likes": 5 }
]

你不能單靠 ->0->1 去一筆一筆查,太不實用。

這時候 PostgreSQL 提供的函式 jsonb_array_elements() 就派上用場了。

這個函式可以:

  • 一個 JSON 陣列 拆解成 多筆資料列
  • 搭配 LATERAL 使用,可處理巢狀資料
  • 讓你可以對每筆陣列元素做個別查詢、計算、統計

語法解析

jsonb_array_elements(jsonb_value) AS alias

這段語法是 PostgreSQL 處理 JSON 陣列時非常關鍵的一步,它的用途可以用一句話來概括:

把一個陣列拆成多筆資料列(rows),讓你能對每個元素單獨操作。

我們一層一層來解釋這句語法到底做了什麼。

元件說明
jsonb_array_elements()PostgreSQL 提供的函式,用來展開 JSON 陣列
jsonb_value一段 JSONB 格式的資料,這必須是一個陣列,否則會報錯
AS alias幫展開出來的每一筆元素命名一個暫時的別名,你後面才能寫 alias->>'欄位' 來存取每個元素的內容

功能說明:從「一欄一筆」變成「一欄多筆」

假設你原本的 data 欄位長這樣:

{
  "user": {
    "name": "Alice",
    "posts": [
      { "title": "第一篇", "likes": 10 },
      { "title": "第二篇", "likes": 5 }
    ]
  }
}

你想把 posts 裡面那兩篇文章「個別列出來」,不想它們卡在同一個陣列裡。

這時你就可以這樣寫:

FROM users,
LATERAL jsonb_array_elements(data->'user'->'posts') AS post

這段語法會:

  1. 進入 data->'user'->'posts' 陣列
  2. jsonb_array_elements() 把這個陣列展開
  3. 每一個貼文物件變成一筆獨立資料列
  4. 並用 AS post 指定每一筆展開出來的資料命名為 post

🔍 展開前 vs 展開後

展開前(原始 JSON 陣列)

iddata
1{"user": {"name": "Alice", "posts": [ {...}, {...} ] }}

展開後(每筆貼文一行)

usernamepost
Alice{ "title": "第一篇", "likes": 10 }
Alice{ "title": "第二篇", "likes": 5 }

這樣一來,你就可以在 SELECT 裡用 post->>'title'post->>'likes' 等語法,像查普通資料表欄位一樣,操作每一筆貼文資料。

💬 為什麼這叫「打平」?

所謂的「打平」意思是:原本是一欄裡面放一整包陣列資料,經過 jsonb_array_elements() 後,這包資料被「攤開」,每個元素獨立變成一列。

  • 想像你有一個紙箱(這是 posts 陣列)
  • 裡面裝了很多張寫有筆記的小紙條(每一張是貼文物件)
  • 在箱子沒打開前,從外面看就是一個箱子(只佔一筆欄位)
  • 當你把紙箱打開,把每張紙條一張張攤開來排在桌上
  • 你就能一張張看、一張張分析、甚至一張張丟掉、加起來!

這個「打開紙箱 → 攤開內容物」的動作,就是資料庫裡的「打平」。

接下來我們會進一步說明 LATERAL 的角色,幫你破解它看似神秘、其實超實用的本質!


LATERAL 是什麼?為什麼少了它查詢會錯?

🎯 先說結論:

當你在 FROM 中使用一個需要依賴其他欄位值的函式時,LATERAL 可以讓它正確存取每一列的資料。

🧩 我們先來看一個你很熟的查詢語法:

SELECT
  data->'user'->>'name' AS username,
  post->>'title' AS post_title
FROM users,
     jsonb_array_elements(data->'user'->'posts') AS post;

這段的目的是什麼?你希望:

  • 先從 users 表中抓出每一筆 data
  • 再從每一筆資料裡的 posts 陣列中,把所有貼文「展開」
  • 每篇貼文變成一筆資料列,讓你可以查標題和按讚數

聽起來很合理,語法也沒錯太多,但你忘了一件事:PostgreSQL 不知道「你現在要抓的是哪一列的 data」!

😵 PostgreSQL 心裡的困惑

當 PostgreSQL 執行這段查詢時,它其實是這樣想的:

好,我知道你叫我展開 data->'user'->'posts' 裡的貼文,

但你沒告訴我是哪一筆 users 的資料,我根本不知道該抓誰的 data 啊!

✅ 加上 LATERAL:就像把展開函式「貼在每一筆資料旁邊」

當你這樣改寫:

FROM users,
LATERAL jsonb_array_elements(data->'user'->'posts') AS post

SQL 執行順序就變了!它會這樣理解:

喔~你是要我「對每一列 users 資料」跑一次 jsonb_array_elements(...),而且是用這一列的 data 來展開 posts 陣列。

我懂了!那我就每列跑一次、展開一次,然後幫你一筆筆貼文列出來。

這就是 LATERAL 的角色。它就像是個「讓函式看得見當前資料列」的標記。

📦 更直觀的比喻:逐列開盒子

想像 users 表長這樣:

iddata(裡面有每個使用者的 posts 陣列)
1一個有 2 篇貼文的使用者
2一個有 3 篇貼文的使用者

現在你想針對每一位使用者,打開他的貼文盒子,把每篇貼文展開列出來。

如果你沒有加 LATERAL,資料庫就像是:

「你跟我說你要展開一個盒子,但你沒有告訴我是哪一位使用者的盒子啊?」

加了 LATERAL,資料庫就知道:

「喔,每一筆資料我都去展開它自己的貼文,沒問題!」

❌ 不加 LATERAL:報錯範例

SELECT ...
FROM users,
     jsonb_array_elements(data->'user'->'posts') AS post;

錯誤訊息可能會長這樣:

ERROR:  invalid reference to FROM-clause entry for table "users"
DETAIL:  There is an entry for table "users", but it cannot be referenced from this part of the query.

這就是 PostgreSQL 告訴你:「你在 FROM 裡寫的函式,不能看前面那個 users 表的欄位。」

為什麼 SQL 要這麼設計?

要真正理解 LATERAL 為什麼必要,我們要先了解 SQL 的執行順序,特別是 FROM 子句的處理邏輯。

🔄 SQL 執行查詢的順序

雖然我們寫查詢的順序通常是:

SELECT ... FROM ... WHERE ... ORDER BY ...

但實際上,SQL 執行時是這樣處理的

  1. FROM:先確定要從哪裡取資料(資料表或子查詢)
  2. JOIN / LATERAL:處理來源之間的關聯
  3. WHERE:套用條件
  4. SELECT:決定要顯示哪些欄位
  5. (後面還有 GROUP BY、ORDER BY 等)

也就是說,在執行 SELECT 之前,SQL 會先處理 FROM 子句裡的所有來源資料

📌 那問題來了:如果你在 FROM 裡面,就需要了一個「還正在確認中的欄位」的函式呢?

像這樣的查詢:

FROM users,
     jsonb_array_elements(data->'user'->'posts') AS post

這裡 jsonb_array_elements() 這個函式想要用的是來自 users 資料表中的 data 欄位。

但根據剛剛提到的執行順序,SQL 在處理 FROM 的每個項目時,是彼此獨立的

在這個階段,usersjsonb_array_elements(...) 是平行的兩個來源,函式是沒辦法自動「回頭」去看 users 的欄位的。

❗️這就違反了 SQL 的邏輯規則:

  • 你說「我想展開每一列使用者的 posts 陣列」
  • 但 SQL 回你:「我現在還沒讀完 users,data 是什麼我不知道,你怎麼能叫我用?」

這就像廚師在備料時,說要準備「這道菜需要的配料」,但你沒給他哪一道菜的名字。

他會問:「我要準備哪一道菜的料?我不知道你指的是哪一道啊!」

加上 LATERAL,就是你告訴他:「這是麻婆豆腐的配料清單,依這道來準備。」

✅ 解法就是:加上 LATERAL

當你這樣寫:

FROM users,
     LATERAL jsonb_array_elements(data->'user'->'posts') AS post

你就是明確地告訴 SQL:

「這個函式不是獨立執行的,它要依附在每一列 users 的資料上,請幫我一列一列跑,讓它每次都可以讀到當前這列的 data 值。」

🧠 為什麼 PostgreSQL 不自動幫你加?

因為這會讓查詢變得不明確、不穩定、難維護

SQL 設計者希望開發者能主動聲明依賴關係,這樣資料庫才能:

  • 清楚知道哪些函式會依賴哪些資料
  • 在執行計畫中做更好的優化
  • 避免語意不清或潛在的模糊行為

✅ 小結:從執行順序理解 LATERAL 的必要性

概念解釋
SQL 先執行 FROM所以 FROM 裡的每個項目要彼此獨立執行
函式想存取上一個資料表的欄位這就打破了平行原則,SQL 不知道你想用哪一列
LATERAL 的作用告訴 SQL:這個函式是「要針對每一筆資料列來執行的」

實戰範例:展開所有貼文,取得每篇的標題與按讚數

🎯 目標:列出每位使用者的所有貼文標題與按讚數

假設我們現在有一張名為 users 的資料表,每筆資料中有一個 data 欄位,裡面是 JSONB 結構如下:

{
  "user": {
    "name": "Alice",
    "posts": [
      { "title": "第一篇", "likes": 10 },
      { "title": "第二篇", "likes": 5 }
    ]
  }
}

這裡的 posts 是一個陣列,裡面包含多篇貼文。我們的目標是把這個陣列展開,讓每一篇貼文都變成一筆資料列,並且能取得:

  • 使用者名稱
  • 每一篇貼文的標題
  • 每一篇貼文的按讚數

✅ 查詢語法

SELECT
  data->'user'->>'name' AS username,
  post->>'title' AS post_title,
  post->>'likes' AS like_count
FROM users,
LATERAL jsonb_array_elements(data->'user'->'posts') AS post;

查詢流程逐步解析

步驟語法片段說明
data->'user'->'posts'從 data 欄位中取出 user 物件,接著進入 posts 陣列。這邊的資料格式仍然是 JSONB 陣列(array),尚未展開。
jsonb_array_elements(...)將剛剛取出的陣列展開,一個元素變成一筆資料列,就是俗稱的「打平」。
AS post幫展開出來的每個元素指定一個別名叫做 post,之後就可以用 post->>'欄位' 來讀取它裡面的值。
LATERAL這是關鍵字,讓 jsonb_array_elements() 可以存取同一筆 users 資料中的其他欄位(這裡是 data)。少了它,查詢會失敗。
post->>'title'、post->>'likes'從展開後的每筆貼文資料中,取出標題與按讚數,並轉為文字格式。

📌 查詢結果會長這樣:

usernamepost_titlelike_count
Alice第一篇10
Alice第二篇5

每一筆資料都是一篇貼文,現在你就可以像處理一般表格資料一樣,對這些貼文做篩選、排序、計算等操作。

展開後的資料可以做什麼?

展開陣列後,你可以針對每篇貼文進行:

1️⃣ 排序

找出讚數最多的貼文:

ORDER BY (post->>'likes')::int DESC

2️⃣ 篩選

只查出按讚數超過 5 的貼文:

WHERE (post->>'likes')::int > 5

3️⃣ 統計

想算出使用者的總讚數、平均讚數,就可以把 post->>'likes' 轉為整數後用聚合函數操作,例如:

SELECT
  data->'user'->>'name' AS username,
  SUM((post->>'likes')::int) AS total_likes,
  AVG((post->>'likes')::int) AS avg_likes
FROM users,
LATERAL jsonb_array_elements(data->'user'->'posts') AS post
GROUP BY username;

🔁 延伸應用:加入條件篩選

以下範例:只列出那些「每篇貼文讚數大於 5」的資料:

SELECT
  data->'user'->>'name' AS username,
  post->>'title' AS post_title
FROM users,
LATERAL jsonb_array_elements(data->'user'->'posts') AS post
WHERE (post->>'likes')::int > 5;

這樣查詢就能排除那些比較冷門的貼文。

使用 jsonb_array_elements() 搭配 LATERAL 是進入 JSONB 實戰應用的核心組合,能讓你從「看得到資料」走向「查得出來資料」,這正是資料查詢邏輯的進階一步。


結語:熟悉語法,駕馭巢狀資料不再是夢

處理巢狀 JSONB 結構,確實需要多一點思考與耐心。但一旦你掌握了這幾個核心工具:

  • ->->> 的基本操作
  • jsonb_array_elements() 拆解陣列
  • LATERAL 正確使用方法

你就能駕馭幾乎任何形式的 JSON 資料結構。多試幾次、寫幾個查詢,從挫折中成長,很快你就會像老手一樣自在地操作巢狀資料。

Similar Posts