マテリアライズドビュー(マテビュー)とは

マテリアライズドビューとは、実際にデータがテーブルに格納されるビューです。

格納されたデータを取得するだけのため、ビューよりはデータ取得が高速な反面、

データは更新しないと古いままのデータになってしまうため、注意が必要です。

 

マテリアライズドビュー(マテビュー)を作成する

マテビューを作成する構文です。

※VIEWを作る構文に「MATERIALIZED」がつく形になります。

 --マテビューを作成する構文
CREATE MATERIALIZED VIEW マテビュー名 AS
SELECT xxx , xxx, … FROM テーブル名;

 

マテビューにINDEXを作成する

マテビューにもテーブルと同じく、INDEXを定義することができます。

--マテビューにINDEXを定義する
CREATE UNIQUE INDEX ON マテビュー名(列1 , 列2 , ・・・);

 

マテビューを更新する

マテビューのデータを更新(=リフレッシュ)する方法です。

マテビューはリフレッシュ中にロックがされるため、リフレッシュが終わるまで待たされる

という欠点があります。(リフレッシュが短い場合は特に気にしなくてもいいですが)

 

解決するには「CONCURRENTLY」オプションをつけることで、

テーブル全体をロックすることなくマテリアライズドビューの更新が行えます。

(オプションをつけるには、INDEXか主キーが作成されている必要があります。)

--通常のリフレッシュ文
REFRESH MATERIALIZED VIEW マテビュー名;

--CONCURRENTLYをつけた方式、ただしこれにはINDEX作成が必要
REFRESH MATERIALIZED VIEW CONCURRENTLY マテビュー名;

 

構文まとめを書いています。ぜひ一度見てみて下さい

「基本構文・こんな時どう書くんだっけ?」をまとめました

なんとなくわかるWindow関数とは

この記事ではWINDOW関数を、サンプルデータを使って

なんとなーくイメージをつかんでもらおうとする記事です。

(なんとなくなので構文の説明はほかのサイトに任せることとします。)

 

そもそもWindow関数とは

Window関数とはデータをWindowという領域で区切り、

その中で合計値を取得したり、ランク付けしたりできるようになります。

 

GROUP BYは行が集約されて結果が取得できますが、WINDOW関数では、

行がまとめられることはなく、それぞれが取得できるのが大きく違います。

 

サンプルデータで実行してみる

生徒とそのテスト結果というデータを用意してみました。

student_name(生徒名)、subject_name(教科)、score(点数)とします。

 

WINDOWS関数の例①

教科でWINDOWを区切った後、合計値、ランク付けをするSQLの例です。

※「PARTITION BY subject_name」で「教科ごとに区切る」を表しています

SELECT 
	--教科
	subject_name, 
	
	--教科でWindowを区切る(PARTITION BY subject_name)
	--教科ごとに、点数の高い順(order by score desc)に生徒を表示する
	rank() OVER(PARTITION BY subject_name order by score desc) AS ranking
	
	--生徒,          点数
	, student_name , score
	
	--教科ごとに合計点を取得する
	, sum(score) OVER (PARTITION BY subject_name) 
FROM test_score;

 

結果はこんな感じ。教科ごとに点数の高い順にデータが並ぶ形になります。

英語の点数が高い生徒、国語の点数が高い生徒、…という形。

(赤い線はわかりやすいように後から引いています)

 

WINDOWS関数の例②

上のSQLは

『PARTITION BY subject_name教科に対しての順位付け)』でしたが、

『PARTITION BY student_name生徒に対しての順位付け)』に変更してみます。

SELECT 
	--生徒名
	student_name, 
	
	--生徒でWindowで区切る(PARTITION BY student_name)
	--生徒ごとに、点数の高い順(order by score desc)に教科を表示する
	rank() OVER(PARTITION BY student_name order by score desc) AS ranking
	
	--教科,           点数
	, subject_name , score
	
	--またその生徒ごとに合計点を取得する
	, sum(score) OVER (PARTITION BY student_name) 
FROM test_score;

 

すると結果はこんな感じ。

生徒ごとに教科の点数が高い順に並べた結果になります。

 

なんとなくまとめ

サンプルを2つ提示しましたが、ざっくりとイメージはつかめたでしょうか。

まとめるとWINDOW関数とは…

・WINDOWという区切りを作り、その中で集計やランク付けができる

・GROUP BYは結果が集計されるが、WINDOW関数は集計されない

というものでした。

 

構文まとめを書いています。ぜひ一度見てみて下さい

「基本構文・こんな時どう書くんだっけ?」をまとめまし

ビュー(VIEW)を作成する構文

--ビューを作成する
CREATE OR REPLACE VIEW ビュー名 AS
SELECT xxx , xxx, … FROM テーブル名; 

--ビューを作成する例1
create view employee_vw as 
select employee_code , employee_name , department_code from employee;

--ビューを作成する例2(列の指定はアスタリスクでも可)
create view employee_vw as select * from employee;

※VIEWへの参照権限があれば、元のテーブルへの参照権限は不問です。

 

 

ビュー(VIEW)を削除する構文

--ビューを削除する
DROP VIEW ビュー名;

--ビューを削除する例
DROP VIEW employee_vw;

 

 

 

ビューへのSELECT権限を付与する

--ビューへのSELECT権限を付与する
GRANT SELECT ON ビュー名 TO ロール名;     --SELECT権限を付与する

--ビュー「employee_vw」へのSELECT権限を付与する例
GRANT SELECT ON employee_vw TO postgres;

 

 

ビューへのSELECT権限を削除する

--ビューへのSELECT権限を削除する
REVOKE ALL PRIVILEGES ON ビュー名 FROM ロール名;  --SELECT権限を削除する

--ビュー「employee_vw」へのSELECT権限を削除する例
REVOKE SELECT ON employee_vw FROM postgres;

 

生成列を定義する

PostgreSQL12から使用可能になった『生成列』を使用する方法を紹介します。

 

 

生成列とは

生成列とは、『式で表現される列』です。

といってもわかりづらいので、例えば身長と体重があるテーブルで、

『BMIという列名、計算式は体重÷身長の2乗」と定義した列を作ることができます。

あらかじめ作っておけば取得や登録する前に、計算をせずにすむメリットがあります。

 

 

生成列の構文

生成列の構文を紹介します。これ単体で使用するのではなく、

テーブルのCREATE文でこの文を使用し、生成列を定義します。

列名 型 GENERATED ALWAYS AS 式 STORED

 

 

生成列の例(CASE文を使用した例)

上の構文を使ったCREATE文の例です。

CREATE TABLE test
(   ・・・
    height numeric,   -- 身長
    weight numeric,   -- 体重
    --生成列 : BMI( 体重 ÷ 身長(m)の2乗)の作成
    bmi numeric(3,1) GENERATED ALWAYS AS (weight / ((height / 100) * (height / 100))) STORED,
    ・・・
)

 

 

上の例のBMIでは、単に計算結果の列でしたが、

次の文はCASE文を使用した場合分けの例です。

CREATE TABLE test
(   ・・・ , 
    --生成列の例1:列「category」による場合分け
    hoge text GENERATED ALWAYS AS (    -- この列の定義はここから
    CASE 
    WHEN category '1' THEN '一般職'
    WHEN category '2' THEN '管理職'
    WHEN category '3' THEN '派遣'
    WHEN category '4' THEN '再雇用' 
    ELSE 'それ以外' END
    ) STORED                          -- ここまでです
    
    , ・・・
    , 

    --生成列の例2 : 誕生日によるクラス分け
    class_name text GENERATED ALWAYS AS
    (
     CASE 
     WHEN birthday between '2016/4/1' and '2017/3/31' THEN 'Aクラス' 
     WHEN birthday between '2017/4/1' and '2018/3/31' THEN 'Bクラス' 
     WHEN birthday between '2018/4/1' and '2019/3/31' THEN 'Cクラス' 
     WHEN birthday between '2019/4/1' and '2020/3/31' THEN 'Dクラス' 
     WHEN birthday between '2020/4/1' and '2021/3/31' THEN 'Eクラス' 
     ELSE '対象外' END) STORED

    , ・・・
)

 

テーブルに列を追加、削除する

テーブルに列を追加、削除する方法です。

--列を追加する構文
ALTER TABLE テーブル名 add 列名 型;

--例:「m_school」テーブルに列「address」を追加する
ALTER TABLE m_school add address character varying(100);


--列を削除する構文
ALTER TABLE テーブル名 DROP COLUMN 列名;

--例:「m_school」テーブルの列「address」を削除する
ALTER TABLE m_school DROP COLUMN address;

 

 

列の桁数を変更する

テーブルの列の桁数を変更する例です。

桁を変更する構文は型を変更する構文と同じになります。

--桁数を変更する
ALTER TABLE テーブル名 ALTER COLUMN 列名 型;

--例:「student」テーブルの列「height」の定義をnumeric(3,1)に変更する
ALTER TABLE student ALTER COLUMN height TYPE numeric(3,1);

 

 

関連記事

列にデフォルト値(初期値)を追加・削除する方法

列にNOT NULL制約を追加・削除する方法

外部キーを追加・削除する方法

 

データベース、テーブル、列へコメントを追加する方法

データベースやテーブル、列にコメントを追加するにはCOMMENT ONを使用します。

 

 

コメントを追加する構文

--データベースへコメントを追加する
COMMENT ON DATABASE データベース名 IS 'コメントです'; 

--テーブルへコメントを追加する
COMMENT ON TABLE テーブル名 IS 'コメントです';

--列へコメントを追加する
COMMENT ON COLUMN テーブル名.列名 IS 'コメントです';

 

コメントを削除する構文

--データベースのコメントを削除する
COMMENT ON DATABASE データベース名 IS NULL;

--テーブルのコメントを削除する
COMMENT ON TABLE テーブル名 IS NULL;

--列へコメントのコメントを削除する
COMMENT ON COLUMN テーブル名.列名 IS NULL;

 

 

コメントはpgAdminで確認できます

コメントはpgAdminで確認できます。

例えばテーブルのコメントは、テーブルのSQL画面で確認できます。

 

 

構文まとめを書いています。ぜひ一度見てみて下さい

「基本構文・こんな時どう書くんだっけ?」をまとめました

日時、時刻の書式設定をする

日付、時刻の書式設定の例です。(そのまま実行できますので試してみて下さい。)

--年月日時分の書式
select to_char(now(),'YYYY/MM/DD HH24:MI:SS'); --2020/04/01 22:34:56

--年月日の書式
select to_char(now(),'YYYYMMDD');       --20200401
select to_char(now(),'YYYY/MM/DD');     --2020/04/01
select to_char(now(),'YYYY.MM.DD');     --2020.04.01
select to_char(now(),'YYYY年MM月DD日');  --2020年04月01日

--月日の書式
select to_char(now(),'MMDD');           --0401
select to_char(now(),'MM/DD');          --04/01
select to_char(now(),'MM.DD');          --04.01
select to_char(now(),'MM月DD日');       --04月01日

--時刻の書式
select to_char(now(), 'HH:MI:SS');      --10:34:56(12時間表記)
select to_char(now(), 'HH24:MI:SS');    --22:34:56(24時間表記)
select to_char(now(), 'HH24時MI分SS秒'); --22時34分56秒

 

書式の指定(頻出なもの)は次のとおりです。

書式 結果
 YYYY  年(4桁)
 YY  年(下2桁)
 MM  月(01-12)
 DD  日(01-31)
 HH  時(01-12)
 HH12  時(01-12)
 HH24  時(01-23)
 MI  分(00-59)
 SS  秒(00-59)

 

 

こちらも参考にどうぞ

現在日時、システム日時の取得

文字から日付に変換する、書式を設定する方法

 

現在日時、システム日時の取得

現在日時の取得例です。(そのまま実行できますので試してみて下さい。)

--今日の日付の取得
select current_date;      --"2020-10-01"

--現在時刻の取得(時刻のみ)
select current_time;      --"22:00:00.000000+09"

--現在日時の取得   ※now()とcurrent_timestampの違いはありません
select now();             --"2020-10-01 22:00:00.000000+09"
select current_timestamp; --"2020-10-01 22:00:00.000000+09"

 

 

現在日時、システム日時の書式設定

日付の書式設定の一例を示します。

--'YYYY/MM/DD'形式で表示する
select to_char(now(), 'YYYY/MM/DD');  --2020/10/01

--'YYYY/MM/DD HH24:MI:SS'形式で表示する
select to_char(now(), 'YYYY/MM/DD HH24:MI:SS'); --2020/10/01 12:34:56

 

 

関連記事(日付)

日時、時刻の書式設定をする(yyyymmdd形式)

日付の加算、週の加算、月の加算

2つの日付の差を計算する

誕生日から年齢を計算する

 

ランダム値を生成する方法

ランダム値を生成するにはrandomを使用します。

 

 

ランダム値を生成する構文

--ランダム値を生成する(引数は必要ありません)
random() 

--範囲を指定したランダム値を生成する方法
--最小値と最大値のところに値を当てはめて実行して下さい
select round(( random() * (最小値 - 最大値) )::numeric, 0) + 最大値;

 

ランダム値を生成する例

select * from random(); --結果例:0.13224(実行する度異なる値が生成)

--範囲指定:最小値=1 , 最大値=100
select round(( random() * (1 - 100) )::numeric, 0) + 100; --結果例:77

--範囲指定:最小値=1 , 最大値=10,000
select round(( random() * (1 - 10000) )::numeric, 0) + 10000; --結果例:7000

 

 

構文まとめを書いています。ぜひ一度見てみて下さい

「基本構文・こんな時どう書くんだっけ?」をまとめました

余りを計算する方法

数値の余りを求めるにはmodを使います。

modを応用することで偶数・奇数の処理を分けることができます。

 

余りを計算する(mod関数)の構文

mod関数は次のように使用します。

--余りを計算する構文
mod( 数値,割る数 ) 

--余りを求める
select mod(10,3);  -- 1( 10 ÷ 3 の余り )
select mod(5,3);   -- 2( 5 ÷ 3 の余り )
select mod(6,3);   -- 0( 6 ÷ 3 の余り )

 

偶数奇数によって処理を分ける

2で割った余りが0なら偶数、1なら奇数というように奇数・偶数の判断が可能です。

--偶数の時、奇数の時と処理を分ける例
select case when mod(2,1) = 0 then '偶数の時の処理' 
else '奇数の時の処理' end;

 

構文まとめを書いています。ぜひ一度見てみて下さい

「基本構文・こんな時どう書くんだっけ?」をまとめました