general notes

いろいろなまとめ

達人に学ぶSQL徹底指南書 1-1 CASE式のススメ①

既存のコード体系を新しい体系に変換して集計する

テーブル定義

use PracticeSQL

create table tbl1_1(
    pref_name nvarchar(50),
    population int
)

insert into tbl1_1(pref_name, population) values
    ('徳島', 100),
    ('香川', 200),
    ('愛媛', 150),
    ('高知', 200),
    ('福岡', 300),
    ('佐賀', 100),
    ('長崎', 200),
    ('東京', 400),
    ('群馬', 50)

-- 県コードを地方コードに再分類する
select 
    case 
        when pref_name = '徳島' then '四国'
        when pref_name = '香川' then '四国'
        when pref_name = '愛媛' then '四国'
        when pref_name = '高知' then '四国'
        when pref_name = '福岡' then '九州'
        when pref_name = '佐賀' then '九州'
        when pref_name = '長崎' then '九州'
        else 'その他'
    end district,
    sum(population) as 人口合計
from tbl1_1
group by
    case
        when pref_name = '徳島' then '四国'
        when pref_name = '香川' then '四国'
        when pref_name = '愛媛' then '四国'
        when pref_name = '高知' then '四国'
        when pref_name = '福岡' then '九州'
        when pref_name = '佐賀' then '九州'
        when pref_name = '長崎' then '九州'
        else 'その他'
    end

--district 人口合計
--その他    450
--九州   600
--四国   650

異なる条件の集計を1つのSQLで行う

テーブル定義

use PracticeSQL

create table tbl1_1_2(
    pref_name nvarchar(50),
    gender int,
    population int
)

insert into tbl1_1_2(pref_name, gender, population) values
    ('徳島', 1, 60),
    ('徳島', 2, 40),
    ('香川', 1, 100),
    ('香川', 2, 100),
    ('愛媛', 1, 100),
    ('愛媛', 2, 50),
    ('高知', 1, 100),
    ('高知', 2, 100),
    ('福岡', 1, 100),
    ('福岡', 2, 200),
    ('佐賀', 1, 80),
    ('佐賀', 2, 20),
    ('長崎', 1, 125),
    ('長崎', 2, 125),
    ('東京', 1, 250),
    ('東京', 2, 150)

-- 男女別人口の集計
select 
    pref_name,
    sum(case when gender = '1' then population else 0 end) as cnt_m,
    sum(case when gender = '2' then population else 0 end) as cnt_f
from tbl1_1_2
group by pref_name

--pref_name    cnt_m   cnt_f
--愛媛   100 50
--香川   100 100
--高知   100 100
--佐賀   80  20
--長崎   125 125
--東京   250 150
--徳島   60  40
--福岡   100 200

CHECK制約の練習

(本当はCASE式を使うのだが、SQLServerだと通らない…)

use PracticeSQL

--給与は20万円以下
create table tbl1_1_3(
    gender int,
    salary int constraint check_salary check(
        salary <= 200000
    )
)

insert into tbl1_1_3 values (1, 199999)
insert into tbl1_1_3 values (2, 200001)

--(1 行処理されました)
--メッセージ 547、レベル 16、状態 0、行 12
--INSERT ステートメントは CHECK 制約 "check_salary" と競合しています。競合が発生したのは、データベース "PracticeSQL"、テーブル "dbo.tbl1_1_3", column 'salary' です。
--ステートメントは終了されました。

条件を分岐させたUPDATE

2回ロジックを通すと給与Down⇒給与Upみたいなことになるので、CASE式で処理するのが吉らしい

テーブル定義

use PracticeSQL

create table tbl1_1_4(
    name nvarchar(50),
    salary int
)

insert into tbl1_1_4(name, salary) values
    ('相田', 300000),
    ('神崎', 270000),
    ('木村', 220000),
    ('斎藤', 290000)

--次のようなupdateを行う
-- 1.現在の給料が30万円以上の社員は、10%の減給とする
-- 2.現在の給料が25万以上28万未満の社員は、20%の昇給とする

update tbl1_1_4
set salary = case 
    when 300000 <= salary then salary * 0.9
    when 250000 <= salary and salary < 280000 then salary * 1.2
    else salary 
end

--name salary
--相田   270000
--神崎   324000
--木村   220000
--斎藤   290000