Skip to main content

SELECT DISTINCT

這段查詢在做什麼?

SELECT DISTINCT document_id
FROM public.fleet_rv_model_manuals
WHERE model_id = $1
AND document_id > 0
AND deleted_at_unix_ms IS NULL
ORDER BY document_id;

語意可以拆成三層:

  1. 篩選:同一個 model_id、有效的 document_id、尚未軟刪除
  2. 去重:同一份 document_id 只保留一筆
  3. 排序:依 document_id 由小到大回傳

常見情境:一張「model ↔ document」關聯表裡,同一個 document_id 可能出現多列(例如不同版本、不同語系、或歷史列),但業務上只要「這台 model 有哪些文件 ID 清單」。


DISTINCT 是什麼?

SELECT DISTINCT 會對結果列做去重:選出的欄位組合若完全相同,只保留一列。

寫法效果
SELECT document_id同一 document_id 出現幾次就回幾列
SELECT DISTINCT document_id同一 document_id 只回一列

只對你 SELECT 出來的欄位去重,不是對整張表的主鍵去重。


用表格看差異

假設 fleet_rv_model_manuals 有這些列($1 = 10):

model_iddocument_iddeleted_at_unix_ms
10101NULL
10101NULL
10102NULL
100NULL
101031710000000000
20101NULL

套用 WHERE 後剩下:

document_id
101
101
102

再套 DISTINCT

document_id
101
102

最後 ORDER BY document_id 依序回傳 101102

被濾掉的原因:

  • document_id = 0 → 不符合 document_id > 0
  • deleted_at_unix_ms 有值 → 不符合 IS NULL(軟刪除)
  • model_id = 20 → 不符合 $1

條件逐行說明

條件用意
model_id = $1參數化查詢,只看指定 model(避免 SQL injection)
document_id > 0排除無效/佔位用的 0
deleted_at_unix_ms IS NULL只取未軟刪除的列
DISTINCT document_id同一文件只出現一次
ORDER BY document_id讓結果穩定、可預期

PostgreSQL 注意事項

ORDER BYDISTINCT

在 PostgreSQL 裡,ORDER BY 的欄位通常要出現在 SELECT 清單中(或可由其推導)。本例排序的是 document_id,與 SELECT 一致,沒問題。

DISTINCT vs GROUP BY

只取唯一值時,兩者常可互換:

-- 寫法 A
SELECT DISTINCT document_id
FROM public.fleet_rv_model_manuals
WHERE model_id = $1
AND document_id > 0
AND deleted_at_unix_ms IS NULL
ORDER BY document_id;

-- 寫法 B(等價意圖)
SELECT document_id
FROM public.fleet_rv_model_manuals
WHERE model_id = $1
AND document_id > 0
AND deleted_at_unix_ms IS NULL
GROUP BY document_id
ORDER BY document_id;

需要聚合(COUNTMAX…)時改用 GROUP BY;單純去重用 DISTINCT 較直覺。

DISTINCT ON(PostgreSQL 專用)

若要「每個 document_id 保留一整列,且自訂保留哪一列」,可用 DISTINCT ON

SELECT DISTINCT ON (document_id) *
FROM public.fleet_rv_model_manuals
WHERE model_id = $1
AND document_id > 0
AND deleted_at_unix_ms IS NULL
ORDER BY document_id, created_at_unix_ms DESC; -- 同 document_id 取最新一列

ORDER BY第一個欄位必須與 DISTINCT ON 一致。本篇範例只要 ID 清單,用一般 DISTINCT 即可。


小結

  • DISTINCT:對選出的欄位組合去重。
  • 本查詢 = 篩出某 model 的有效文件 → 去重 → 排序。
  • 關聯表常會對同一外鍵產生多列,列表 API 回「有哪些 ID」時,DISTINCT 很常見。