DISTINCT ONとは
PostgreSQLのDISTINCT ONは「特定のカラムごとに先頭の1行だけを取得する」 ためのPostgreSQL独自の構文です。
例えば以下のようなデータがあったとします。
DROP TABLE IF EXISTS staff;
CREATE TABLE staff (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
job TEXT
);
INSERT INTO staff (name, job) VALUES
('Sato', 'Developer'),
('Tanaka', 'Manager'),
('Suzuki', 'Developer'),
('Yamada', 'Designer'),
('Kobayashi', 'Developer'),
('Fujimoto', 'Manager'),
('Shimizu', 'Designer'),
('Yoshida', 'Analyst');
SELECT * FROM staff;| id | name | job |
|---|---|---|
| 1 | Sato | Developer |
| 2 | Tanaka | Manager |
| 3 | Suzuki | Developer |
| 4 | Yamada | Designer |
| 5 | Kobayashi | Developer |
| 6 | Fujimoto | Manager |
| 7 | Shimizu | Designer |
| 8 | Yoshida | Analyst |
重複除去は「SELECT DISTINCT ON (job) * FROM staff;」で実行できますが、この書き方だと、重複除去した際にどの行が残るかを制御できません。
SELECT DISTINCT ON (job) * FROM staff;| id | name | job |
|---|---|---|
| 8 | Yoshida | Analyst |
| 4 | Yamada | Designer |
| 5 | Kobayashi | Developer |
| 6 | Fujimoto | Manager |
上からidの昇順で2つ目以降の重複を除去する場合は、重複除去の部分をサブクエリにして以下のように書きます。
SELECT *
FROM (
SELECT DISTINCT ON (job) * FROM staff
ORDER BY job, id
) sub
ORDER BY id;| id | name | job |
|---|---|---|
| 1 | Sato | Developer |
| 2 | Tanaka | Manager |
| 4 | Yamada | Designer |
| 8 | Yoshida | Analyst |
逆に重複しているものの最後以外を除去したい場合は「ORDER BY job, id desc」にします。
SELECT *
FROM (
SELECT DISTINCT ON (job) * FROM staff
ORDER BY job, id desc
) sub
ORDER BY id;| id | name | job |
|---|---|---|
| 5 | Kobayashi | Developer |
| 6 | Fujimoto | Manager |
| 7 | Shimizu | Designer |
| 8 | Yoshida | Analyst |
PostgreSQLのDISTINCT ONを知っている人は多いですが、重複しているレコードの最初または最後以外を除去して並び替える方法まで理解している人は少ないです。
この重複除去の方法を知っておけば、必ず役立ちます。



