LoginSignup
0
0

あのSQLはActiveRecordを使ってどう書くのか(CASE編)

Posted at

達人に学ぶSQL徹底指南書を読んで知見を得つつ、
これRailsのActiveRecordで書こうと思ったらどうなるのかと思ったのでやってみた

CASE式

select, group

下記の様に、県から地方単位に人口を集計したいとする
image.png

これを一発で行うには

SELECT
  CASE prefecture_name
    WHEN '徳島' then '四国'
    WHEN '香川' then '四国'
    WHEN '愛媛' then '四国'
    WHEN '高知' then '四国'
    WHEN '福岡' then '九州'
    WHEN '佐賀' then '九州'
    WHEN '長崎' then '九州'
    ELSE 'その他'
  END AS district,
  sum(population)
FROM prefectures
GROUP BY `district`

と、CASE式を使い、group byでCASE式のエイリアスを指定してやれば可能
これをActiveRecordでやると

Population.select("
    case prefecture_name
        when '徳島' then '四国'
        when '香川' then '四国'
        when '愛媛' then '四国'
        when '高知' then '四国'
        when '福岡' then '九州'
        when '佐賀' then '九州'
        when '長崎' then '九州'
        else 'その他'
    end as district,
    sum(population) as population
")
.group(:district)

selectの中をゴリゴリ書く必要がある... 🦍

scopeを作ってやればすっきりして可読性は増す、気がする

scope :per_region, -> (){
    select("
        case prefecture_name
        when '徳島' then '四国'
        when '香川' then '四国'
        when '愛媛' then '四国'
        when '高知' then '四国'
        when '福岡' then '九州'
        when '佐賀' then '九州'
        when '長崎' then '九州'
        else 'その他' end as district
    ")
    .group(:district)
}
Population.per_region.select("sum(population) as population")

update

updateのset句でもCASEは使用できる

以下の様に、
1️⃣給料が30万以上の社員は、給料を10%減
2️⃣給料が25万以上28万未満の社員は、給料を20%増
という更新をしたい

image.png

1️⃣と2️⃣でupdate文を一回ずつ流すと、欲しい結果が得られないので失敗する
1回のupdateで終わらせるには、
set句でCASEを使用すれば可能

UPDATE salaries
SET salary = CASE 
  WHEN salary >= 300000 THEN salary * 0.9
  WHEN salary >= 250000 AND salary < 280000 THEN salary * 1.2
  ELSE salary
END;

これをActiveRecordで実行する場合

Salary.update_all("
    salary = CASE 
      WHEN salary >= 300000 THEN salary * 0.9
      WHEN salary >= 250000 AND salary < 280000 THEN salary * 1.2
      ELSE salary 
    END;
")

う~ん... そのまんま書き過ぎ? ( ŏㅁŏ;)

効率的なクエリは複雑になるから、
逆にSQLビルダーライブラリでは対応し切れないということなのだろうか?

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0