かっちゃんのプログラミング奮闘記

このブログは、僕がプログラミング学習をしていく上で、知識のインプットを図るためのアウトプット場所として活用している場所です。

【SQL】集計関数やグループ分けに関すること

今回は値を計算する集計関数や、各列で同じ行内容を1つにグループ化したり、そのグループ化したものを計算する方法などに関することを学んだので、メモ書き程度にアウトプットしていきます。

集計関数

まずそもそもなのですが、集計関数はSELECT文でしか利用できないです。

理由は、集計関数は、その名の通り、集計したものを計算してくれるものなので、集計するために検索して選択しないとそもそも始まらないからです。

代表的な集計関数

f:id:kazuki13070311:20210901232844p:plain
代表的な集計関数

集計関数の計算は、集計の対象となる全ての行に対して、まとめて1回のみ行われる。

なので、どれだけ行数があろうとも、基本的に返される結果は1つだけ。

ただし、そこはグループ化してから計算したりすると、各項目ごとに計算を行うこともできるので、そこは後ほど書く。

集計関数の記述方法

基本的に「集計関数(列名)」で実行する。
また計算結果の列名は、 ASで変更することができる。

SELECT
   SUM(出金額) AS 合計金額,
   AVG(出金額) AS 平均出勤額
 FROM 家計簿

GROUP BY(データのグループ化)

各行の同一項目で複数個同じ名前の行が存在している時、それらを1つにグループ化してまとめることができる。

そのグループ化は「GROUP BY」を使用することで行うことができる。

なので、例えば費目列に交際費が3つあった場合、その交際費を1つにまとめてくれる。

交際費            交際費
交際費            水道費
水道費      →     光熱費
光熱費  (グループ化)
交際費

グループ化して計算する基本構文

 SELECT グループ化したい列名, 集計関数
   FROM テーブル名
  (WHERE 絞り込み条件)
 GROUP BY グループ化したい列名

 SELECT 費目, SUM(出金額) AS 費目別の出金額合計
   FROM 家計簿
 GROUP BY 費目

グループ化ごの集計計算の処理の動きとしては、まず、SELECT文とWHERE句で対象の列を検索し、その次にグループ化し、最後に集計計算が行われて、グループごとに答えが返ってくる。

Railsでも同じ動きがある

group(:カラム名)

Railsでも「group」メソッドを使用することで、同じ様にグループ化して処理を行うことができる。

pikawaka.com

集計結果はHAVING句で絞り込む

グループ分けされた後にまたWHERE句で絞り込みをしようとするとエラーになります。

なのでこういう場合は、HAVING句を使用します。

HAVING句はWHERE句とよく似ているが、HAVING句は集計関数が全て完了した最後に実行されて絞り込みが行われるので、その点が少し違う。

グループ化してから絞り込む記述方法

 SELECT グループ化したい列名, 集計関数
   FROM テーブル名
  (WHERE 絞り込み条件)
 GROUP BY グループ化したい列名
HAVING 集計結果に対する絞り込み条件

 SELECT 費目, SUM(出金額) AS 費目別の出金額合計
   FROM 家計簿
 GROUP BY 費目
HAVING SUM(出金額) > 0

この様に記述することで、家計簿テーブルの費目を集計した後に、出金額が0を含まない、0以上のものだけ結果として返す様に命令できる。

なので、処理の流れとして、 SELECTやWHEREでまず絞り込み検索をし、その後に各列名ごとにグループ化が行われ、それらに対して集計関数で計算が行われ、最後にHAVINGで計算結果を特定条件で絞り込こんで答えを返す。

RailsでもHAVINGがある

Railsでロジックを組む時にも、このHAVINGを使ってグループ分けされたものを条件式に沿って絞り込みして戻り値として返すことができる。

group(:カラム名).having("条件式")

havingメソッドとwhereメソッドの違い

余談ですが、Railsでのhavingメソッドとwhereメソッドは処理が似ていますが、各々で処理されるタイミングが違います。

・whereメソッドはgroupメソッドが実行される前のデータを対象に絞り込みを行う
・havingメソッドはgroupメソッドが実行されてグループ化された後のデータを抽出して絞り込み処理を行う

似ている様でwhereはグループ化される前に実行されて、havingはグループ化された後に実行されるということなので、処理のタイミングが違うので注意する。