PostgreSQLのスキーマ定義とデータ操作入門

データベースとテーブルの作成

PostgreSQL環境での開発は、ストレージ単位であるデータベースの作成から始まります。

CREATE DATABASE meteorology_db;

不要になったデータベースは、以下のコマンドで物理的に削除します。

DROP DATABASE meteorology_db;

テーブル構造の定義

観測データを格納するメインテーブルと、地域マスター情報を管理する補助テーブルを作成します。カラム名とデータ型は業務要件に合わせて設計します。

CREATE TABLE observation_logs (
    location_id     varchar(50),
    low_temp        integer,
    high_temp       integer,
    precipitation   double precision,
    record_date     date
);

CREATE TABLE location_master (
    location_id     varchar(50) PRIMARY KEY,
    geo_position    point
);

テーブルの破棄は DROP TABLE を使用し、依存関係に注意して実行します。

DROP TABLE location_master;
DROP TABLE observation_logs;

レコードの投入

スキーマが構築できたら、INSERT INTO 文を用いてデータを取り込みます。カラムリストを明示的に記述することで、値の順序不一致によるエラーを未然に防ぎます。

INSERT INTO observation_logs (location_id, low_temp, high_temp, precipitation, record_date)
VALUES ('Kyoto', 8, 15, 2.5, '2023-11-10');

INSERT INTO location_master (location_id, geo_position)
VALUES ('Kyoto', '(135.7681, 35.0116)');

-- カラムを指定し、任意の順序で値を挿入
INSERT INTO observation_logs (record_date, location_id, high_temp, low_temp)
VALUES ('2023-11-12', 'Nara', 17, 10);

データ抽出と条件指定

格納された情報にアクセスするには SELECT 文を構築します。基礎的な抽出、算術演算、ソート、重複排除の構文を確認します。

基礎抽出と列計算

SELECT * FROM observation_logs;

-- 特定カラムの抽出と平均気温の算出
SELECT location_id, (high_temp + low_temp) / 2.0 AS avg_temp, record_date
FROM observation_logs;

フィルタリングとソート

-- 降水量が0より大きい日の京都データを取得
SELECT * FROM observation_logs
WHERE location_id = 'Kyoto' AND precipitation > 0.0;

-- 地域IDと最低気温の昇順で並べ替え
SELECT * FROM observation_logs ORDER BY location_id, low_temp;

-- 重複した地域名の排除
SELECT DISTINCT location_id FROM observation_logs ORDER BY location_id;

複数テーブルの結合

異なるテーブルに跨がるデータを一体化するには結合演算子を使用します。可読性と保守性を高めるため、PostgreSQLでは明示的な JOIN 構文の採用が推奨されます。

内部結合 (INNER JOIN)

結合条件を満たす行のみに絞って結果を返します。

SELECT o.location_id, o.low_temp, o.high_temp, o.precipitation, o.record_date, m.geo_position
FROM observation_logs o
INNER JOIN location_master m ON o.location_id = m.location_id;

左外部結合 (LEFT OUTER JOIN)

左テーブルの全レコードを保持し、右テーブルに一致しない場合は NULL で補完します。

SELECT o.location_id, o.low_temp, o.high_temp, o.precipitation, o.record_date, m.geo_position
FROM observation_logs o
LEFT OUTER JOIN location_master m ON o.location_id = m.location_id;

自己結合 (Self Join)

同一テーブルを別名で2回参照し、行同士の比較処理を行います。

SELECT 
    s1.location_id AS area_a, s1.low_temp AS min_a, s1.high_temp AS max_a,
    s2.location_id AS area_b, s2.low_temp AS min_b, s2.high_temp AS max_b
FROM observation_logs s1
JOIN observation_logs s2 
    ON s1.low_temp < s2.low_temp
    AND s1.high_temp > s2.high_temp;

集約処理とグループ化

複数行のデータに対して統計計算を実行するには、集約関数と GROUP BY 句を組み合わせて利用します。

極値の取得とサブクエリ

-- データセット全体の最低気温の最大値を算出
SELECT MAX(low_temp) FROM observation_logs;

-- 該当値を記録した地域を特定
SELECT location_id FROM observation_logs
WHERE low_temp = (SELECT MAX(low_temp) FROM observation_logs);

グループ化後の条件絞込み (HAVING)

グループ化された結果セットに対して条件を適用するには HAVING 句を使用します。

-- 各都市における最低気温の最大値を計算
SELECT location_id, MAX(low_temp) AS peak_low
FROM observation_logs
GROUP BY location_id;

-- 集約値が20未満のグループのみ抽出
SELECT location_id, MAX(low_temp)
FROM observation_logs
GROUP BY location_id
HAVING MAX(low_temp) < 20;

-- WHERE(集約前)とHAVING(集約後)の併用
SELECT location_id, MAX(low_temp)
FROM observation_logs
WHERE location_id LIKE 'K%'
GROUP BY location_id
HAVING MAX(low_temp) < 20;

タグ: PostgreSQL SQL DDL DML 集約関数

10月10日 10:31 投稿