$ man max-min
MAX / MIN
集約関数最大値・最小値を返す。返るのは値だけで、その値をもつ行は返らない。
呼び出しの形
MAX(式) MIN(式)
つまずきやすいところ
返るのは値だけです。その値をもつ行は返りません。行がほしいなら副問い合わせか
ORDER BY ... LIMITを使ってください。ORDER BY ... LIMIT 1は同点があっても 1 行しか返しません。同点を全部ほしいなら副問い合わせで比べてください。NULL は無視されます。対象が 0 行のときは NULL です(
SUMと同じ)。文字列の大小は照合順序(collation)で決まります。この例で
MIN(name)が「中村」になるのは文字コード順だからで、日本語話者が期待する五十音順ではありません。読み仮名の列を別に持って並べ替えるのが確実です。
実行例
結果は実際に流したものです。同じ SQL を 自由に打てる画面 で試すと、同じ結果になります。
SELECT MAX(salary) AS saidai, MIN(salary) AS saishou, MAX(hired_on) AS saishin_nyusha, MIN(name) AS jishoujun_saisho FROM shain
| saidai | saishou | saishin_nyusha | jishoujun_saisho |
|---|---|---|---|
| 980000 | 398000 | 2026-06-01 | 中村 |
1 行
文字列は照合順序、日付は時間順で比べられます。⚠️ ここでの文字列の最小が「中村」なのは文字コード順だからで、五十音順ではありません。
SELECT name, salary FROM shain WHERE salary = (SELECT MAX(salary) FROM shain)
| name | salary |
|---|---|
| 鈴木 | 980000 |
1 行
副問い合わせで最大値を求めてから絞ります。同点があれば全部返ります。
SELECT name, MAX(salary) FROM shain
実行するとこうなります
ERROR: column "shain.name" must appear in the GROUP BY clause or be used in an aggregate function
「最高給与の人の名前」はこの書き方では取れません。
説明
MAX と MIN は、対象の中の最大値・最小値を返します。数値だけでなく、文字列や日付にも使えます(辞書順・時間順で比べます)。
⚠️ いちばん多い誤解は、その値をもつ行が返ってくると思ってしまうことです。返るのは値だけなので、SELECT name, MAX(salary) FROM shain のように書いても「給与が最高の人の名前」にはなりません(そもそもエラーになります)。
「最大値をもつ行」がほしいときは、次のどちらかで書きます。
ORDER BY salary DESC LIMIT 1… 1 行だけでよいとき。同点があると 1 行しか出ませんWHERE salary = (SELECT MAX(salary) FROM shain)… 同点も全部ほしいとき
NULL は無視します。すべて NULL、または対象が 0 行のときは NULL を返します。
次に読む
根拠にした一次情報
- PostgreSQL 18 マニュアル: 集約関数(2026-09-02 確認)