【PostgreSQL入門】データの抽出~SELECT~

はじめに

データベースを扱う上で最も頻繁に使用するのが、データを取り出す操作です。PostgreSQLでは、SELECT文を使ってテーブルに保存されたデータを自由自在に抽出できます。

本記事では、PostgreSQL 16におけるSELECT文の基本から応用まで、実践的な例を交えながら丁寧に解説します。データベース初心者の方でも、この記事を読み終える頃には、業務で使える実用的なデータ抽出スキルが身につくでしょう。

この記事で分かること

この記事を読むことで、以下のスキルを習得できます。

  • SELECT文の基本構文と使い方
  • 特定の列だけを取り出す方法
  • WHERE句を使った条件指定によるデータ絞り込み
  • ORDER BY句を使ったデータの並び替え
  • LIMIT句を使った取得件数の制限
  • 複数の条件を組み合わせた高度な検索方法
  • 実務で役立つSELECT文の応用テクニック

稼働環境

本記事の操作は、以下の環境で動作確認を行っています。

  • OS: Windows Server 2025(64bit)
  • データベース: PostgreSQL16
  • 接続ツール: psql(PostgreSQL標準コマンドラインツール)

※他のOSやPostgreSQLのバージョンでも基本的な操作は同じですが、一部の機能や表示が異なる場合があります。

サンプルテーブルの準備

実際にSELECT文を試すため、まずサンプルデータを含むテーブルを作成しましょう。以下のSQL文を実行してください。

PostgreSQL
-- 社員テーブルの作成
CREATE TABLE employees (
    employee_id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    department VARCHAR(50),
    salary INTEGER,
    hire_date DATE
);

-- サンプルデータの挿入
INSERT INTO employees (name, department, salary, hire_date) VALUES
('山田太郎', '営業部', 350000, '2020-04-01'),
('佐藤花子', '開発部', 420000, '2019-07-15'),
('鈴木一郎', '営業部', 380000, '2021-01-10'),
('田中美咲', '人事部', 320000, '2022-03-01'),
('高橋健太', '開発部', 450000, '2018-10-20'),
('伊藤真由美', '営業部', 360000, '2020-08-15'),
('渡辺拓也', '開発部', 400000, '2021-06-01');

このコマンドを実行すると、7名の社員情報を持つテーブルが作成されます。

SELECT文の基本構文

PostgreSQLにおけるSELECT文の基本構文は次の通りです。

PostgreSQL
SELECT 列名1, 列名2, ...
FROM テーブル名
WHERE 条件
ORDER BY 並び替えの基準
LIMIT 取得件数;

それぞれの要素について、順番に詳しく見ていきましょう。

全データの取得

最もシンプルなSELECT文は、テーブルの全データを取得する方法です。アスタリスク(*)を使うことで、すべての列を一度に取得できます。

PostgreSQL
SELECT * FROM employees;

このクエリを実行すると、employeesテーブルに保存されているすべての社員データが表示されます。開発段階でテーブルの内容を確認したいときに便利な方法です。

特定の列だけを取得

実際の業務では、すべての列が必要とは限りません。必要な列だけを指定して取得することで、データ転送量を削減し、処理速度を向上させられます。

PortgreSQL
SELECT name, department FROM employees;

このクエリでは、社員名と所属部署の2列だけを取得します。複数の列を指定する場合は、カンマで区切って記述します。

WHERE句による条件指定

WHERE句を使うと、特定の条件に合致するデータだけを抽出できます。これはデータベース操作の中でも特に重要な機能です。

等価条件での絞り込み

特定の値と一致するデータを取得する例です。

PostgreSQL
SELECT * FROM employees
WHERE department = '開発部';

このクエリは、開発部に所属する社員だけを抽出します。文字列を条件に使う場合は、シングルクォーテーションで囲む必要があります。

比較演算子を使った条件

数値データに対しては、大小比較を使った条件指定が可能です。

PostgreSQL
SELECT name, salary FROM employees
WHERE salary >= 400000;

この例では、給与が40万円以上の社員を抽出しています。PostgreSQLで使える主な比較演算子は以下の通りです。

  • = : 等しい
  • <> または != : 等しくない
  • > : より大きい
  • < : より小さい
  • >= : 以上
  • <= : 以下

複数条件の組み合わせ(AND)

複数の条件をすべて満たすデータを取得するには、ANDを使います。

PostgreSQL
SELECT * FROM employees
WHERE department = '営業部'
AND salary > 350000;

このクエリは、営業部に所属し、かつ給与が35万円を超える社員を抽出します。ANDで結んだ条件は、すべてを同時に満たす必要があります。

複数条件の組み合わせ(OR)

いずれかの条件を満たすデータを取得するには、ORを使います。

PostgreSQL
SELECT * FROM employees
WHERE department = '開発部'
OR salary >= 400000;

このクエリは、開発部に所属しているか、または給与が40万円以上の社員を抽出します。ORで結んだ条件は、どちらか一方を満たせば該当します。

日付条件での絞り込み

日付型のデータに対しても条件を指定できます。

PostgreSQL
SELECT name, hire_date FROM employees
WHERE hire_date >= '2020-01-01';

この例では、2020年1月1日以降に入社した社員を抽出しています。日付もシングルクォーテーションで囲んで指定します。

LIKE演算子によるあいまい検索

完全一致ではなく、部分的な一致でデータを検索したい場合は、LIKE演算子を使用します。

PostgreSQL
SELECT * FROM employees
WHERE name LIKE '%田%';

この例では、名前に「田」という文字を含む社員を検索します。パーセント記号(%)は任意の文字列を表すワイルドカードです。

  • '田%' : 「田」で始まる
  • '%田' : 「田」で終わる
  • '%田%' : 「田」を含む

また、アンダースコア(_)を使うと、任意の1文字を表現できます。

PostgreSQL
SELECT * FROM employees
WHERE name LIKE '___太郎';

このクエリは、「〇〇〇太郎」のように、太郎の前に3文字がある名前を検索します。

IN演算子による複数値の指定

複数の値のいずれかに一致するデータを取得する場合、IN演算子が便利です。

PostgreSQL
SELECT * FROM employees
WHERE department IN ('営業部', '開発部');

この例では、営業部または開発部に所属する社員を抽出します。ORを何度も書くよりも、コードが読みやすくなります。

BETWEEN演算子による範囲指定

数値や日付の範囲を指定する場合は、BETWEEN演算子が使えます。

PostgreSQL
SELECT name, salary FROM employees
WHERE salary BETWEEN 350000 AND 400000;

このクエリは、給与が35万円以上40万円以下の社員を抽出します。BETWEENは境界値を含む点に注意してください。

NULL値の扱い

データベースでは、値が存在しないことを表すNULLという特殊な値があります。NULLかどうかを判定するには、専用の演算子を使います。

PostgreSQL
-- NULLのデータを検索
SELECT * FROM employees
WHERE department IS NULL;

-- NULLでないデータを検索
SELECT * FROM employees
WHERE department IS NOT NULL;

通常の比較演算子(=や<>)はNULLに対して使えないため、必ずIS NULLまたはIS NOT NULLを使用してください。

ORDER BY句によるデータの並び替え

取得したデータを特定の順序で並び替えるには、ORDER BY句を使用します。

昇順での並び替え

PostgreSQL
SELECT * FROM employees
ORDER BY salary;

この例では、給与の低い順(昇順)に社員データを表示します。デフォルトは昇順(ASC)なので、ASCキーワードは省略可能です。

降順での並び替え

PostgreSQL
SELECT * FROM employees
ORDER BY salary DESC;

DESCキーワードを追加することで、給与の高い順(降順)に並び替えられます。

複数列での並び替え

PostgreSQL
SELECT * FROM employees
ORDER BY department, salary DESC;

この例では、まず部署名で昇順に並び替え、同じ部署内では給与の高い順に並び替えます。カンマで区切って複数の並び替え条件を指定できます。

LIMIT句による取得件数の制限

大量のデータから上位数件だけを取得したい場合、LIMIT句を使用します。

PostgreSQL
SELECT * FROM employees
ORDER BY salary DESC
LIMIT 3;

このクエリは、給与が高い順に上位3名の社員データを取得します。ページネーション機能を実装する際にも、LIMITは非常に重要な役割を果たします。

OFFSET句と組み合わせたページング処理

OFFSETを使うと、指定した件数分だけデータをスキップできます。

PostgreSQL
SELECT * FROM employees
ORDER BY employee_id
LIMIT 3 OFFSET 3;

この例では、最初の3件をスキップして、4件目から6件目までを取得します。Webアプリケーションで「次のページ」機能を実装する際に活用できます。

DISTINCT句による重複行の除外

重複したデータを除いて、一意な値だけを取得したい場合はDISTINCTを使います。

PostgreSQL
SELECT DISTINCT department FROM employees;

このクエリは、社員テーブルに存在する部署名を重複なく一覧表示します。同じ部署に複数の社員がいても、部署名は1回だけ表示されます。

集計関数との組み合わせ

SELECT文では、データを集計する関数も使用できます。

PostgreSQL
-- 社員数のカウント
SELECT COUNT(*) FROM employees;

-- 平均給与の計算
SELECT AVG(salary) FROM employees;

-- 最高給与の取得
SELECT MAX(salary) FROM employees;

-- 最低給与の取得
SELECT MIN(salary) FROM employees;

-- 給与の合計
SELECT SUM(salary) FROM employees;

これらの集計関数は、データ分析やレポート作成で頻繁に使用されます。

GROUP BY句によるグループ化

特定の列でデータをグループ化し、グループごとに集計を行うことができます。

PostgreSQL
SELECT department, COUNT(*), AVG(salary)
FROM employees
GROUP BY department;

このクエリは、部署ごとの社員数と平均給与を計算します。GROUP BYを使う際は、SELECT句に指定する列は、GROUP BYで指定した列か集計関数のいずれかである必要があります。

HAVING句によるグループの絞り込み

GROUP BYで作成したグループに対して条件を適用するには、HAVING句を使います。

PostgreSQL
SELECT department, AVG(salary)
FROM employees
GROUP BY department
HAVING AVG(salary) >= 380000;

この例では、平均給与が38万円以上の部署だけを表示します。WHERE句は個別の行に対する条件、HAVING句はグループに対する条件という違いがあります。

実践的なSELECT文の例

ここまで学んだ知識を組み合わせた、より実践的な例を見てみましょう。

PostgreSQL
SELECT
    department,
    COUNT(*) AS employee_count,
    AVG(salary) AS avg_salary,
    MAX(salary) AS max_salary,
    MIN(salary) AS min_salary
FROM employees
WHERE hire_date >= '2020-01-01'
GROUP BY department
HAVING COUNT(*) >= 2
ORDER BY avg_salary DESC;

このクエリは以下の処理を行います。

  1. 2020年以降に入社した社員に絞り込み
  2. 部署ごとにグループ化
  3. 各部署で2名以上の社員がいる部署のみ抽出
  4. 部署ごとの人数、平均給与、最高給与、最低給与を計算
  5. 平均給与の高い順に並び替え

AS句を使って列に別名(エイリアス)を付けることで、結果がより分かりやすくなります。

つまずきポイントと解決策

PostgreSQLのSELECT文を使う際、初心者がよく遭遇するエラーと解決方法を紹介します。

エラー1: 列名の指定ミス

エラーメッセージ: column "列名" does not exist

原因: 存在しない列名を指定している、または列名のスペルミスがあります。

解決策: テーブル定義を確認し、正確な列名を使用してください。PostgreSQLは大文字小文字を区別することがあるので注意が必要です。

PostgreSQL
-- テーブルの列名を確認
\\d employees

エラー2: 文字列の引用符忘れ

エラーメッセージ: syntax error at or near "営業部"

原因: 文字列値をシングルクォーテーションで囲んでいません。

解決策: 文字列は必ずシングルクォーテーションで囲みます。

PostgreSQL
-- 誤り
SELECT * FROM employees WHERE department = 営業部;

-- 正しい
SELECT * FROM employees WHERE department = '営業部';

エラー3: GROUP BYでのエラー

エラーメッセージ: column "列名" must appear in the GROUP BY clause or be used in an aggregate function

原因: GROUP BY句を使用する際、SELECT句に指定した列がGROUP BYに含まれていないか、集計関数でラップされていません。

解決策: SELECT句の列は、GROUP BYに含めるか、集計関数を使用してください。

PostgreSQL
-- 誤り
SELECT name, department, AVG(salary)
FROM employees
GROUP BY department;

-- 正しい(nameを削除)
SELECT department, AVG(salary)
FROM employees
GROUP BY department;

-- または正しい(nameをGROUP BYに追加)
SELECT name, department, AVG(salary)
FROM employees
GROUP BY department, name;

エラー4: NULLの比較ミス

エラーメッセージ: 特にエラーは出ませんが、期待したデータが取得できません。

原因: NULL値に対して通常の比較演算子を使用しています。

解決策: NULLの判定には必ずIS NULLまたはIS NOT NULLを使用します。

PostgreSQL
-- 誤り(データが取得できない)
SELECT * FROM employees WHERE department = NULL;

-- 正しい
SELECT * FROM employees WHERE department IS NULL;

エラー5: ORDER BYの位置ミス

エラーメッセージ: syntax error at or near "ORDER"

原因: ORDER BY句をWHERE句の前に書いてしまっています。

解決策: SQL文の句の順序を守ってください。正しい順序は、SELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY → LIMITです。

PostgreSQL
-- 誤り
SELECT * FROM employees ORDER BY salary WHERE department = '営業部';

-- 正しい
SELECT * FROM employees WHERE department = '営業部' ORDER BY salary;

パフォーマンス向上のヒント

大量のデータを扱う場合、SELECT文の書き方によって処理速度が大きく変わります。

必要な列だけを指定する

PostgreSQL
-- 遅い(すべての列を取得)
SELECT * FROM large_table;

-- 速い(必要な列だけ取得)
SELECT id, name FROM large_table;

アスタリスク(*)は開発時の確認には便利ですが、本番環境では必要な列だけを明示的に指定しましょう。

WHERE句で早期に絞り込む

PostgreSQL
-- データを絞り込んでから処理
SELECT department, AVG(salary)
FROM employees
WHERE hire_date >= '2020-01-01'
GROUP BY department;

可能な限り早い段階でデータ量を減らすことで、後続の処理が高速になります。

インデックスを活用する

頻繁に検索条件に使う列にはインデックスを作成することで、検索速度が劇的に向上します。

PostgreSQL
-- departmentにインデックスを作成
CREATE INDEX idx_department ON employees(department);

インデックスについては、シリーズの別記事で詳しく解説する予定です。

よくある質問(FAQ)

Q1: SELECTとSELECT ALLの違いは何ですか?

PostgreSQLでは、SELECTとSELECT ALLは同じ動作をします。ALLキーワードは省略可能で、デフォルトでALLが適用されます。重複行を除外したい場合は、SELECT DISTINCTを使用してください。

Q2: 大文字小文字は区別されますか?

SQLのキーワード(SELECT、FROM、WHEREなど)は大文字小文字を区別しません。ただし、テーブル名や列名を二重引用符で囲んだ場合は区別されます。また、文字列データの比較では大文字小文字が区別されます。大文字小文字を区別せずに検索したい場合は、ILIKEを使用するか、LOWER関数で統一してから比較してください。

Q3: 複数のテーブルからデータを取得するにはどうすればよいですか?

複数のテーブルからデータを取得するには、JOIN句を使用します。JOINについては、このシリーズの次回以降の記事で詳しく解説します。基本的な例を示すと次のようになります。

PostgreSQL
SELECT e.name, d.department_name
FROM employees e
JOIN departments d ON e.department_id = d.department_id;

Q4: 計算結果に基づいて並び替えることはできますか?

はい、可能です。ORDER BY句では、計算式や集計関数の結果に基づいて並び替えできます。

PostgreSQL
SELECT name, salary, salary * 12 AS annual_salary
FROM employees
ORDER BY annual_salary DESC;

Q5: 同じ値を持つ行が複数ある場合、どの順序で返されますか?

ORDER BY句を指定しない場合、PostgreSQLはデータベース内部の物理的な格納順序でデータを返しますが、この順序は保証されません。特定の順序が必要な場合は、必ずORDER BY句を使用してください。また、ORDER BYで指定した列に同じ値がある場合、その中での順序は不定です。完全に順序を制御したい場合は、複数の列を指定してください。

まとめ

本記事では、PostgreSQL 16におけるSELECT文の基本から応用まで、幅広く解説しました。重要なポイントをまとめます。

SELECT文はデータベース操作の基本であり、最も頻繁に使用するSQL文です。基本的な全件取得から始まり、WHERE句による条件指定、ORDER BY句での並び替え、LIMIT句での件数制限など、段階的に学習することで確実にスキルアップできます。

実務では、これらの要素を組み合わせて複雑なクエリを作成します。GROUP BYやHAVING句を使った集計処理は、データ分析やレポート作成に不可欠なスキルです。また、パフォーマンスを意識したSQL文の書き方も重要になります。

まずは基本的なSELECT文から始めて、少しずつ複雑な条件や機能を追加していくことで、実践的なデータベーススキルが身につきます。サンプルデータを使って、本記事で紹介した様々なパターンを実際に試してみてください。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール