general notes

いろいろなまとめ

tkinterで4択クイズアプリを開発

下記サイトの写経です。

daeudaeu.com

import csv
import random
import tkinter
from tkinter import messagebox

# https://daeudaeu.com/tkinter_quiz/

CSV_FILE = "quiz.csv"
class Quiz():

    def __init__(self, master):
        # master : クイズ画面を配置するウィジェット
        self.master = master
        self.quiz_list = []
        self.now_quiz = None
        self.choice_value = tkinter.IntVar()

        self.getQuiz()
        self.createWidgets()
        self.showQuiz()


    def getQuiz(self):
        with open(CSV_FILE, encoding="utf-8") as f:
            csv_data = csv.reader(f)
            for quiz in csv_data:
                self.quiz_list.append(quiz)


    def createWidgets(self):
        self.frame = tkinter.Frame(
            self.master,
            width=400,
            height=200,
        )
        self.frame.pack()

        self.button = tkinter.Button(
            self.master,
            text="OK",
            command=self.checkAnswer
        )
        self.button.pack(pady=5)

    def showQuiz(self):

        num_quiz = random.randrange(len(self.quiz_list))
        quiz = self.quiz_list[num_quiz]

        self.problem = tkinter.Label(
            self.frame,
            text=quiz[0]
        )

        self.problem.grid(
            column=0,
            row=0,
            columnspan=4,
            pady=10
        )

        self.choices = []
        for i in range(4):
            choice = tkinter.Radiobutton(
                self.frame,
                text=quiz[i+1],
                variable=self.choice_value,
                value=i
            )
            choice.grid(
                row=1,
                column=i,
                padx=10,
                pady=10
            )
            self.choices.append(choice)

        self.quiz_list.remove(quiz)
        self.now_quiz = quiz


    def checkAnswer(self):
        if self.choice_value.get() == int(self.now_quiz[5]):
            messagebox.showinfo("結果", "正解です!!")
        else:
            messagebox.showinfo("結果", "不正解です…")

        self.deleteQuiz()

        if self.quiz_list:
            self.showQuiz()
        else:
            self.endAppli()

    def deleteQuiz(self):
        self.problem.destroy()

        for choice in self.choices:
            choice.destroy()

    def endAppli(self):
        self.problem = tkinter.Label(
            self.frame,
            text="クイズは全て出題済みです"
        )

        self.problem.grid(
            column=0,
            row=0,
            padx=10,
            pady=10
        )

        self.button.config(
            command=self.master.destroy
        )



app = tkinter.Tk()
quiz = Quiz(app)
app.mainloop()

tkinter で「ストップウォッチ」アプリを作成

下記サイトの写経です。 daeudaeu.com

import tkinter
import time

# https://daeudaeu.com/stopwatch/

INTERVAL = 5
start_time = 0
start_flg = False
after_id = 0

app = tkinter.Tk()
app.title("stop watch")
app.geometry("250x200")

def update_time():
    global start_time
    global app, label
    global after_id

    after_id = app.after(INTERVAL, update_time)
    now_time = time.time()

    elapsed_time = now_time - start_time
    elapsed_time_str = "{:.2f}".format(elapsed_time)
    label.config(text=elapsed_time_str)

def start():
    global app
    global start_time
    global start_flg
    global after_id

    if not start_flg:
        start_flg = True
        start_time = time.time()
        after_id = app.after(INTERVAL, update_time)

def stop():
    global start_flg
    global after_id

    if start_flg:
        app.after_cancel(after_id)
        start_flg = False

def reset():
    if not start_flg:
        label.config(text="0.00")


# 時刻表示
label = tkinter.Label(
    app,
    text="0.00",
    width=6,
    font=("", 50, "bold"),
)
label.pack(pady=5)

#スタートボタン
start_button = tkinter.Button(
    app,
    text="START",
    command=start
)
start_button.pack(pady=5)

#ストップボタン
start_button = tkinter.Button(
    app,
    text="STOP",
    command=stop
)
start_button.pack(pady=5)

#リセットボタン
start_button = tkinter.Button(
    app,
    text="RESET",
    command=reset
)
start_button.pack(pady=5)

app.mainloop()


達人に学ぶSQL徹底指南書 1-4 HAVING句の力

データの歯抜けを探す

テーブル定義

create table tbl1_4_1_SeqTbl(
    seq int,
    name varchar(10)
)

insert into dbo.tbl1_4_1_SeqTbl values
    (1, 'ディック'),
    (2, 'アン'),
    (3, 'ライル'),
    (5, 'カー'),
    (6, 'マリー'),
    (8, 'ベン')

-- seqの歯抜けチェック
select '歯抜けあり' as gap from dbo.tbl1_4_1_SeqTbl
having count(*) <> max(seq);
--歯抜けの最小値を探す
select min(seq + 1) as gap from dbo.tbl1_4_1_SeqTbl
where (seq+1) not in (select seq from dbo.tbl1_4_1_SeqTbl)
--gap
--4

--not exists版
select min(seq + 1) as gap from dbo.tbl1_4_1_SeqTbl a
where not exists (select * from dbo.tbl1_4_1_SeqTbl b where a.seq + 1 = b.seq)
--gap
--4

最頻値を求める

テーブル定義

create table tbl1_4_3_Graduates(
    name nvarchar(10),
    income int
)

insert into dbo.tbl1_4_3_Graduates values
    ('a', 400000),
    ('b', 30000),
    ('c', 20000),
    ('d', 20000),
    ('e', 20000),
    ('f', 15000),
    ('g', 15000),
    ('h', 10000),
    ('i', 10000),
    ('j', 10000)

--最頻値を求める(allの利用)
select income, count(*) as cnt from dbo.tbl1_4_3_Graduates
group by income
having count(*) >= all(
    select count(*) from dbo.tbl1_4_3_Graduates
    group by income
)

--income   cnt
--10000    3
--20000    3
--最頻値を求める(maxの利用)
select income, count(*) as cnt from dbo.tbl1_4_3_Graduates
group by income
having count(*) >= (
    select max(cnt) from(
        select count(*) as cnt from dbo.tbl1_4_3_Graduates
        group by income
    ) tmp
)
--income   cnt
--10000    3
--20000    3

中央値(メジアン)を求める

--メジアンを求める
select avg(distinct income) as median from(
    select t1.income from dbo.tbl1_4_3_Graduates t1, dbo.tbl1_4_3_Graduates t2
    group by t1.income
    having sum(case when t2.income >= t1.income then 1 else 0 end) >= count(*) / 2
        and sum(case when t2.income <= t1.income then 1 else 0 end) >= count(*) / 2
) tmp

--median
--17500

NULLを含まない集合を探す

テーブル定義

create table tbl1_4_5_Students(
    id int,
    dpt nvarchar(10),
    submit_date date
)

insert into dbo.tbl1_4_5_Students values
    (100, '理学部', '2005-10-10'),
    (101, '理学部', '2005-09-22'),
    (102, '文学部', null),
    (103, '文学部', '2005-09-10'),
    (200, '文学部', '2005-09-22'),
    (201, '工学部', null),
    (202, '経済学部', '2005-09-25')

--提出日にnullを含まない(=全員提出)学部を選択する
select dpt from dbo.tbl1_4_5_Students
group by dpt
having count(*) = sum(
    case when submit_date is not null then 1 else 0 end
)

関係除算でバスケット解析

テーブル定義

create table tbl1_4_6_Items(
    item nvarchar(10)
)

insert into dbo.tbl1_4_6_Items values
    ('ビール'),
    ('紙オムツ'),
    ('自転車')

create table tbl1_4_6_ShopItems(
    shopname nvarchar(10),
    item nvarchar(10)
)

insert into dbo.tbl1_4_6_ShopItems values
    ('仙台', 'ビール'),
    ('仙台', '紙オムツ'),
    ('仙台', '自転車'),
    ('仙台', 'カーテン'),
    ('東京', 'ビール'),
    ('東京', '紙オムツ'),
    ('東京', '自転車'),
    ('大阪', 'テレビ'),
    ('大阪', '紙オムツ'),
    ('大阪', '自転車')

--Itemsテーブルの商品を全て備えた店を探すSQL(他の物があってもよい)
select si.shopname from dbo.tbl1_4_6_ShopItems si, dbo.tbl1_4_6_Items i
where si.item = i.item
group by si.shopname
having count(si.item) = (select count(item) from dbo.tbl1_4_6_Items)
--shopname
--仙台
--東京
--Itemsテーブルの商品を全て備えた店を探すSQL(他の物があるとダメ)
select si.shopname 
from dbo.tbl1_4_6_ShopItems si
left outer join dbo.tbl1_4_6_Items i
on si.item = i.item
group by si.shopname
having count(si.item) = (select count(item) from dbo.tbl1_4_6_Items)
    and count(i.item) = (select count(item) from dbo.tbl1_4_6_Items)
--shopname
--東京

達人に学ぶSQL徹底指南書 1-3 3値論理とNULL

3値論理の真理表

(t = true, u = unknown, f = false)

  • NOT
x NOT x
t f
u u
f t
  • AND
AND t u f
t t u f
u u u f
f f f f
  • OR
OR t u f
t t t t
u t u u
f t u f

排中律の不成立

テーブル定義

create table tbl1_3_1_Students(
    name nvarchar(10),
    age int
)

insert into tbl1_3_1_Students values
    ('ブラウン', 22),
    ('ラリー', 19),
    ('ジョン', null),
    ('ボギー', 21)

select * from tbl1_3_1_Students where age = 20 or age <> 20;
--ジョンの行が出力されない
--name age
--ブラウン 22
--ラリー    19
--ボギー    21
select * from tbl1_3_1_Students where age = 20 or age <> 20 or age is null;
--3値論理での条件網羅
--name age
--ブラウン 22
--ラリー    19
--ジョン    NULL
--ボギー    21

not in とnot existsの違い

テーブル定義

create table tbl1_3_2_ClassA(
    name nvarchar(10),
    age int,
    city nvarchar(10),
)

insert into tbl1_3_2_ClassA values
    ('ブラウン', 22, '東京'),
    ('ラリー', 19, '埼玉'),
    ('ボギー', 21, '千葉')

create table tbl1_3_2_ClassB(
    name nvarchar(10),
    age int,
    city nvarchar(10),
)

insert into tbl1_3_2_ClassB values
    ('斎藤', 22, '東京'),
    ('田尻', 23, '東京'),
    ('山田', NULL, '東京'),
    ('和泉', 18, '千葉'),
    ('武田', 20, '千葉'),
    ('石川', 19, '神奈川')

-- Bクラスの東京在住の生徒と年齢が一致しないAクラスの生徒を選択するSQL?
select * from tbl1_3_2_ClassA
where age not in (
    select age from tbl1_3_2_ClassB where city ='東京'
)
-- 結果がない

where age not in (...)はwhere age <> x1 and age <> x2 and ... と同義であるが、このときage <> nullという条件式があるとunknownが発生し、どのxに対しても"where unknown"という評価になり、結果が出力されない。

-- 本当にやりたかったこと
select * from tbl1_3_2_ClassA a
where not exists (
    select * from tbl1_3_2_ClassB b where a.age = b.age and b.city ='東京'
)
--name age city
--ラリー    19  埼玉
--ボギー    21  千葉

exists述語はtrueかfalseしか返さないため、unknownはfalseに評価される。

限定述語と極値関数の違い

ClassBのテーブルで東京在住の人の全ての人の年齢よりも低い年齢のClassAのテーブルの人を抽出する。

-- 限定述語 all を使う
select * from dbo.tbl1_3_2_ClassA
where age < all(
    select age from dbo.tbl1_3_2_ClassB 
    where city = '東京'
)
-- 結果の出力なし

限定述語の where age < all(...)はwhere age < x1 and age < x2 and ... と同義であるため、age < nullという条件式があると上記同様"where unknown"と評価され、結果が出力されない。

-- 極値関数 min を使う
select * from dbo.tbl1_3_2_ClassB
where age < (
    select min(age) from dbo.tbl1_3_2_ClassB 
    where city = '東京'
)
--name age city
--和泉   18  千葉
--武田   20  千葉
--石川   19  神奈川

極値関数はnullを集計に含めないため、nullを除いたageで最小値が求められる。ただし集計の対象がない場合はnullになるため注意。

達人に学ぶSQL徹底指南書 1-2 自己結合の使い方

重複順列・順列・組み合わせ

テーブル定義

use PracticeSQL

create table tbl1_2_1_Products(
    prod_name nvarchar(10),
    price int
)

insert into tbl1_2_1_Products values
    ('りんご', 100),
    ('みかん', 50),
    ('バナナ', 80)

-- prod_nameの重複順列
select p1.prod_name as name1, p2.prod_name as name2
from tbl1_2_1_Products p1, tbl1_2_1_Products p2

--name1    name2
--りんご    りんご
--みかん    りんご
--バナナ    りんご
--りんご    みかん
--みかん    みかん
--バナナ    みかん
--りんご    バナナ
--みかん    バナナ
--バナナ    バナナ
-- prod_nameの順列
select p1.prod_name as name1, p2.prod_name as name2
from tbl1_2_1_Products p1, tbl1_2_1_Products p2
where p1.prod_name <> p2.prod_name

--name1    name2
--みかん    りんご
--バナナ    りんご
--りんご    みかん
--バナナ    みかん
--りんご    バナナ
--みかん    バナナ
-- prod_nameの組み合わせ
select p1.prod_name as name1, p2.prod_name as name2
from tbl1_2_1_Products p1, tbl1_2_1_Products p2
where p1.prod_name > p2.prod_name

--name1    name2
--りんご    みかん
--りんご    バナナ
--みかん    バナナ

内容重複行の抽出

テーブル定義

use PracticeSQL

create table tbl1_2_2_Products(
    rowid int identity(1, 1),
    prod_name nvarchar(10),
    price int
)

insert into tbl1_2_2_Products(prod_name, price) values
    ('りんご', 100),
    ('みかん', 50),
    ('みかん', 50),
    ('みかん', 50),
    ('バナナ', 80)

--重複行の抽出
select * from tbl1_2_2_Products p1
where rowid < (
    select max(p2.rowid) from tbl1_2_2_Products p2
    where p1.prod_name = p2.prod_name and p1.price = p2.price
)

--rowid    prod_name   price
--2    みかん   50
--3    みかん   50

部分的に不一致なキーの検索

テーブル定義

use PracticeSQL

create table tbl1_2_3_Addresses(
    name nvarchar(10),
    family_id int,
    address nvarchar(30)
)

insert into tbl1_2_3_Addresses values
    ('前田義明', 100, '東京都港区虎ノ門3-2-29'),
    ('前田由美', 100, '東京都港区虎ノ門3-2-92'),
    ('加藤茶', 200, '東京都新宿区西新宿2-8-1'),
    ('加藤勝', 200, '東京都新宿区西新宿2-8-1'),
    ('ホームズ', 300, 'ベイカー街221B'),
    ('ワトソン', 400, 'ベイカー街221B')

--family_idが同じでaddressが異なるレコードを抽出
select a1.name, a1.address from tbl1_2_3_Addresses a1, tbl1_2_3_Addresses a2
where a1.family_id = a2.family_id and a1.address <> a2.address

--name address
--前田義明 東京都港区虎ノ門3-2-29
--前田由美 東京都港区虎ノ門3-2-92

ランキング

テーブル定義

use PracticeSQL

create table tbl1_2_4_Products(
    name nvarchar(10),
    price int
)

insert into tbl1_2_4_Products values
    ('りんご', 50),
    ('みかん', 100),
    ('ぶどう', 50),
    ('スイカ', 80),
    ('レモン', 30),
    ('バナナ', 50)

-- ランキング算出(OLAP)
select
    name,
    price,
    RANK() over (order by price desc) as rank_1,
    DENSE_RANK() over(order by price desc) as rank_2
from
    tbl1_2_4_Products

--name price   rank_1  rank_2
--みかん    100 1   1
--スイカ    80  2   2
--ぶどう    50  3   3
--りんご    50  3   3
--バナナ    50  3   3
--レモン    30  6   4
-- RANK(自己非等値結合)
select 
    P1.name,
    P1.price,
    (select count(P2.price)
     from tbl1_2_4_Products P2
     where P2.price > P1.price) + 1 as rank_1   
from
    tbl1_2_4_Products P1

--name price   rank_1
--りんご    50  3
--みかん    100 1
--ぶどう    50  3
--スイカ    80  2
--レモン    30  6
--バナナ    50  3
-- DENSE_RANK(自己非等値結合)
select 
    P1.name,
    P1.price,
    (select count(distinct P2.price)
     from tbl1_2_4_Products P2
     where P2.price > P1.price) + 1 as rank_1   
from
    tbl1_2_4_Products P1

--name price   rank_1
--りんご    50  3
--みかん    100 1
--ぶどう    50  3
--スイカ    80  2
--レモン    30  4
--バナナ    50  3
--RANK(外部結合)
select 
    P1.name,
    max(P1.price) as price,
    count(P2.name) + 1 as rank_1    
from
    tbl1_2_4_Products P1
left outer join
    tbl1_2_4_Products P2
on
    P1.price < P2.price
group by
    P1.name

--name price   rank_1
--スイカ    80  2
--バナナ    50  3
--ぶどう    50  3
--みかん    100 1
--りんご    50  3
--レモン    30  6

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

主キーの交換

テーブル定義

use PracticeSQL

create table tbl1_1_5(
    p_key nvarchar(3),
    col_1 int,
    col_2 nvarchar(3)
)

insert into tbl1_1_5(p_key, col_1, col_2) values
    ('a', 1, ''),
    ('b', 2, ''),
    ('c', 3, '')

-- 主キーの入れ替え(aとbの交換)
update tbl1_1_5
set p_key = case 
    when p_key = 'a' then 'b'
    when p_key = 'b' then 'a'
    else p_key 
end

select * from tbl1_1_5

--p_key    col_1   col_2
--b    1   あ
--a    2   い
--c    3   う

テーブル同士のマッチング(IN, EXISTS)

テーブル定義

use PracticeSQL

create table tbl1_1_6_CourseMaster(
    course_id int,
    course_name nvarchar(10)
)

insert into tbl1_1_6_CourseMaster(course_id, course_name) values
    (1, '経理入門'),
    (2, '財務知識'),
    (3, '簿記検定'),
    (4, '税理士')

create table tbl1_1_6_OpenCourses(
    open_month int,
    course_id int
)

insert into tbl1_1_6_OpenCourses(open_month, course_id) values
    (200706, 1),
    (200706, 3),
    (200706, 4),
    (200707, 4),
    (200708, 2),
    (200708, 4)

-- 講座と開催月の対応表出力(in)
select 
    course_name,
    case
        when course_id in (
            select course_id from tbl1_1_6_OpenCourses where open_month = 200706
        ) then 'o'
        else 'x'
    end as '6月',
    case
        when course_id in (
            select course_id from tbl1_1_6_OpenCourses where open_month = 200707
        ) then 'o'
        else 'x'
    end as '7月',
    case
        when course_id in (
            select course_id from tbl1_1_6_OpenCourses where open_month = 200708
        ) then 'o'
        else 'x'
    end as '8月'
from tbl1_1_6_CourseMaster

--course_name  6月    7月    8月
--経理入門 o   x   x
--財務知識 x   x   o
--簿記検定 o   x   x
--税理士    o   o   o
-- 講座と開催月の対応表出力(exists)
select 
    cm.course_name,
    case
        when exists (
            select course_id from tbl1_1_6_OpenCourses oc
            where open_month = 200706
                and oc.course_id = cm.course_id
        ) then 'o'
        else 'x'
    end as '6月',
    case
        when exists (
            select course_id from tbl1_1_6_OpenCourses oc
            where open_month = 200707
                and oc.course_id = cm.course_id
        ) then 'o'
        else 'x'
    end as '7月',
    case
        when exists (
            select course_id from tbl1_1_6_OpenCourses oc
            where open_month = 200708
                and oc.course_id = cm.course_id
        ) then 'o'
        else 'x'
    end as '8月'
from tbl1_1_6_CourseMaster cm

--course_name  6月    7月    8月
--経理入門 o   x   x
--財務知識 x   x   o
--簿記検定 o   x   x
--税理士    o   o   o

CASE式の中で集約関数をつかう

main_club_flgを掛け持ちでなくてもYとするようにすればよい気もする。

テーブル定義

use PracticeSQL

create table tbl1_1_7_StudentClub(
    std_id int,
    club_id int,
    club_name nvarchar(10),
    main_club_flg nvarchar(1)
)

insert into tbl1_1_7_StudentClub values
    (100, 1, '野球', 'Y'),
    (100, 2, '吹奏楽', 'N'),
    (200, 2, '吹奏楽', 'N'),
    (200, 3, 'バドミントン', 'Y'),
    (200, 4, 'サッカー', 'N'),
    (300, 4, 'サッカー', 'N'),
    (400, 5, '水泳', 'N'),
    (500, 6, '囲碁', 'N')

-- 複数のクラブ掛け持ちの人はメインクラブのclub_idを、
-- そうでない人は所属クラブのclub_idを出力
select 
    std_id,
    case
        when count(*) = 1 then max(club_id)
        else max(
            case 
                when main_club_flg = 'Y' then club_id
                else null
            end
        )
    end as main_club_id
from tbl1_1_7_StudentClub
group by std_id

--std_id   main_club_id
--100  1
--200  3
--300  4
--400  5
--500  6

達人に学ぶ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