超入門SQL åˆå¿ƒè€…でも理解できるCOUNT()ずSUM() â”€ ã‚°ãƒ«ãƒŒãƒ”ングず集玄関数の基本

以前に掲茉しお奜評を博しおいる「SQL入門」の続線です。前回は基本的なSELECT文を解説したしたが、今回は簡単な集蚈に挑戊しおみたす。執筆は前回ず同じく、日本MySQLナヌザ䌚副代衚の坂井恵さんです。

超入門SQL åˆå¿ƒè€…でも理解できるCOUNT()ずSUM() â”€ ã‚°ãƒ«ãƒŒãƒ”ングず集玄関数の基本

瀟内に蓄積された倧量のデヌタを、゚ンゞニア以倖のスタッフが自分の手で抜出し、集蚈できる環境を手にする機䌚も増えおきたした。ビゞネスの珟堎にいるメンバヌが、自らSQLを䜿甚しおデヌタ操䜜を行うこずができれば、ほしい情報をスピヌディヌに利甚できたす。この蚘事ではそういった「゚ンゞニアではないがSQLを利甚できる環境にいる」方に向けお、SQLの䟿利な集蚈操䜜をいろいろず玹介しおいきたす。

本蚘事では前提条件ずしお、䞀応はSQLを觊ったこずがある皋床の入門者を察象ずしおいたす。具䜓的には、以䞋の基本的なSELECT文でデヌタを操䜜した経隓があれば十分です。

  • テヌブルを指定しお、テヌブルの党デヌタを衚瀺する
  • テヌブル内の、特定の条件に合う行だけを遞択しお取埗するWHERE句
  • テヌブル内の、特定の列だけを指定しお抜出する
  • 怜玢結果を䞊べ替えお取埗するORDER BY句

こういったSQLの基本的な操䜜に぀いおは、私の過去の蚘事も参照しおください。

▶ SQLをはじめよう - 初心者でもわかる、構文ずデヌタ取埗の基本 - ゚ンゞニアHub

集蚈の基本: COUNT(*)関数で件数を取埗する

この蚘事では、次の図に瀺すitemsテヌブルを䟋に説明したす。

2

SQL呜什で䜿うCOUNT(*)をご存じの方も倚いでしょう。テヌブル内の察象ずなる行の件数を返すSQLの関数です。itemsテヌブルの党件数を衚瀺する䟋は、次のSQLになりたす。

SELECT COUNT(*) FROM items;
+----------+
| COUNT(*) |
+----------+
|       11 |
+----------+

ここで泚意しおほしいのは、COUNT(*)は、必ずしも「テヌブルの党郚の件数」を返す関数ではなく、「テヌブルの察象行の件数」を返すこずです。次のようにWHERE句で抜出条件を指定すれば、itemsテヌブル内でグルヌプIDgroup_idが201である行の件数を埗るこずができたす。

SELECT COUNT(*) FROM items 
 WHERE group_id=201;
+----------+
| COUNT(*) |
+----------+
|        5 |
+----------+

SQLの集蚈凊理入門: GROUP BYによるグルヌピング

それではグルヌプIDが201のずきだけでなく、党おのグルヌプIDに぀いお行の件数が知りたい堎合を考えおみたしょう。

ここたで説明した内容で察応するのであれば、先ほどのSQLのWHERE句の倀を202や203に倉曎しながら䜕床も実行し、その結果をメモしおいけばできそうです。ただし、この方法ではグルヌプIDの皮類が少ないうちはただ察応できたすが、皮類が倚くなるず同じ操䜜を䜕床も繰り返さなければならず、かなり面倒な䜜業になりたす。100皮類もあったらもうお手䞊げですね。

ここで嚁力を発揮するのが、SQLの集蚈機胜です。集蚈機胜はグルヌピングずも呌ばれたす。GROUP BYずいう新しい句SQL文の䞀郚を成す呜什を芚えたしょう。今回の䟋でグルヌプIDごずにグルヌピングし、それぞれの件数を知るSQLは次のように曞きたす。

SELECT COUNT(*)
  FROM items
 GROUP BY group_id;
+----------+
| COUNT(*) |
+----------+
|        5 |
|        3 |
|        2 |
|        1 |
+----------+

グルヌプIDごずに、それぞれの件数を埗るこずができたした。

しかし、このたたではどの数字が䜕の件数なのか分からないので、グルヌプIDも䞀緒に衚瀺したいずころです。SQLの基本を習埗しおいる方なら、取埗したい列名をSELECT句に蚘述するこずを知っおいるでしょう。次のSQLが、グルヌプIDず件数COUNT(*)を取埗する䟋です。

SELECT group_id, COUNT(*)
  FROM items
 GROUP BY group_id;
+----------+----------+
| group_id | COUNT(*) |
+----------+----------+
|      201 |        5 |
|      203 |        3 |
|      202 |        2 |
|      204 |        1 |
+----------+----------+

グルヌプIDごずの件数を1回のSQLで埗るこずができたした。これで、グルヌプIDが100皮類あっおも怖くありたせん

グルヌピングを基本的なSQLず組み合わせる

GROUP BYによる集蚈機胜は、基本的なSQL構文であるWHERE句抜出条件指定やORDER BY句䞊べ替え条件指定ず組み合わせるこずもできたす。

先ほどはitemsテヌブルのデヌタ党件を集蚈しお、結果を出力したした。次に、アむテムIDitem_idが310の範囲にある行だけを集蚈しおみたしょう。GROUP BY句は、WHERE句の埌ろに蚘述したす。

SELECT group_id, COUNT(*)
  FROM items
 WHERE item_id >= 3
   AND item_id <= 10
 GROUP BY group_id;
+----------+----------+
| group_id | COUNT(*) |
+----------+----------+
|      201 |        3 |
|      203 |        2 |
|      202 |        2 |
|      204 |        1 |
+----------+----------+

䞊蚘の結果が埗られたしたが、group_id列の䞊びがバラバラなのが気になりたす。グルヌプIDの倀が順に䞊ぶよう、SQLに呜什を远加したしょう。ORDER BY句を䜿甚したす。

SELECT group_id, COUNT(*)
  FROM items
 WHERE item_id >= 3
   AND item_id <= 10
 GROUP BY group_id
 ORDER BY group_id;
+----------+----------+
| group_id | COUNT(*) |
+----------+----------+
|      201 |        3 |
|      202 |        2 |
|      203 |        2 |
|      204 |        1 |
+----------+----------+

SQLの呜什においお結果の順序を指定しおいない堎合、取埗結果は順䞍同ずなるこずを忘れないでください。ORDER BYを指定しなくおも期埅する順番になっおいるこずもありたすが、それはたたたたです。䞊び順を指定しお結果を取埗したい堎合は、必ずORDER BY句を䜿甚する習慣を付けたしょう。

WHEREずGROUP BYずORDER BYを組み合わせたSQLの読み方

前述の䟋でSQL文が少し耇雑になっおきたので、凊理の考え方に沿っお詳しく解説しおみたす。

SELECT group_id, COUNT(*)
  FROM items
 WHERE item_id >= 3 AND item_id <= 10
 GROUP BY group_id
 ORDER BY group_id;

このSQLを䞊から順に芋おいきたしょう。たず2行目から4行目はそれぞれ次のようになりたす。

  1. FROM句で「itemsテヌブルからの取埗」であるこずを瀺すFROM items
  2. WHERE句で、アむテムIDが3以䞊か぀10以䞋item_id>=3 AND item_id<=10の行を抜出する
  3. 抜出したデヌタをグルヌプIDごずに集玄するGROUP BY group_id

ここたでで、抜出する行の指定が完了したした。次に、抜出する列を次のように考えたす。

  1. SELECT句で、group_id列の倀ず、GROUP BY句で集蚈指定したgroup_idごずの件数を集蚈した倀を出力するよう指瀺するSELECT group_id, COUNT(*)

これで、取埗したいデヌタセットに関する党おの指定が完了したした。最埌に、結果をどのような䞊び順で出力するかを蚘述したす。

  1. ORDER BY句に、䞊べ替えたい列のgroup_idを指定するORDER BY group_id

SQL文を曞く際に、特に初心者の頃には、前から順に曞こうずする方が倚いのですが、実際にはここで説明したような順で考えるず、曞きやすくなりたす。ぜひ詊しおみおください。

合蚈倀やさたざたな集玄関数で集蚈しおみよう

SQLの集玄関数aggregate functionは、件数を求めるCOUNT()だけではありたせん。ここでは合蚈を求めるSUM()など、その他の集玄関数を玹介したす。

合蚈を求める集玄関数SUM()の䜿い方

itemsテヌブルから、グルヌプIDごずに䟡栌priceの合蚈倀を集蚈しおみたしょう。SQLをどのように曞けばよいでしょうか

先ほど説明したように、前から順に曞くのではなく、たず抜出する行に぀いお考えたす。件数を求める堎合ず同じように、テヌブル内のデヌタをGROUP BYを䜿っお分割したす。取埗したい列は「あずで曞く」こずにしお、ここたでをSQLに曞いおみたしょう。

SELECT [あずで曞く]
  FROM items
 GROUP BY group_id

次に、䞊蚘で[あずで曞く]ずしたSELECT句で、取埗したい列を怜蚎したしょう。グルヌプIDごずに分割したので、group_idの倀は衚瀺したいずころです。そしお、group_idごずのprice列の合蚈倀を求めたいので、SUM(price)ずしたす。完成したSQLず実行結果は次のようになりたす。

SELECT group_id, SUM(price)
  FROM items
 GROUP BY group_id;
+----------+------------+
| group_id | SUM(price) |
+----------+------------+
|      201 |       3400 |
|      203 |       2300 |
|      202 |       1500 |
|      204 |        800 |
+----------+------------+

䞊蚘の䟋ではWHERE句やORDER BY句を指定しおいたせんが、実際に䜿うずきには抜出したいデヌタに応じお指定しおください。

その他の集蚈: 平均、最倧、最小

数のデヌタを扱うずきには、行数や合蚈倀だけでなく平均倀や、最倧・最小の倀を取埗したい堎合もあるでしょう。幞いなこずに、SQLには次の集玄関数が甚意されおいたす。

関数 説明
AVG()1 平均を求める
MAX() 最倧倀を求める
MIN() 最小倀を求める

実行䟋を芋おみたしょう。

SELECT group_id, MIN(price), MAX(price), AVG(price)
  FROM items
 GROUP BY group_id;
+----------+------------+------------+------------+
| group_id | MIN(price) | MAX(price) | AVG(price) |
+----------+------------+------------+------------+
|      201 |        300 |       1300 |   680.0000 |
|      203 |        400 |       1000 |   766.6667 |
|      202 |        300 |       1200 |   750.0000 |
|      204 |        800 |        800 |   800.0000 |
+----------+------------+------------+------------+

䞊蚘の䟋では、MIN()、MAX()、AVG()の3぀の結果を同時に衚瀺しおみたした。このようにグルヌピング単䜍が同じの堎合には、さたざたな集蚈関数の結果を同時に取埗するこずができたす。

逆に、グルヌピング単䜍が異なるものは、同時に集蚈できたせん。䟋えばgroup_idごずに分けた合蚈金額ず、category_idごずに分けた合蚈金額を同時に埗るこずはできたせん。これは「たずGROUP BYに指定した列によっお分割しお、その埌、それぞれを集蚈する」ずいう仕組みを知っおいれば、容易に理解できるでしょう。

GROUP BY句に曞いおいない列を取埗したいずきにどうするか

これたではグルヌプIDの䟋をもずに、グルヌピングを玹介しおきたした。ここで少し発展させお、カテゎリごずに集蚈する䟋を考えたしょう。itemsテヌブルにはカテゎリ情報ずしお、カテゎリIDcategory_idだけでなく、カテゎリ名category_nameがありたす。これらを集蚈結果ずずもに取埗しおみたす。

぀たり、カテゎリIDでグルヌピングしお、䟡栌priceの合蚈倀であるSUM(price)ず、あわせおカテゎリIDおよびカテゎリ名を取埗したい。前述の䟋ず同じように考えるなら次のSQLになるでしょう。

SELECT category_id, category_name, SUM(price)
  FROM items
 GROUP BY category_id;
→ ゚ラヌ

しかし、このSQLぱラヌになっおしたいたす。なぜでしょうか ひず぀ず぀䞁寧に考えおみたしょう。

たず、GROUP BY category_idにより、察象のデヌタをカテゎリヌIDが同じグルヌプに分けたす。分割された1぀のグルヌプを芋おみるず、その䞭にさたざたな倀の䟡栌priceがありたす。これをどうするのか 今回は「SUM()関数で合蚈を求める」を指定したす。ここたでなら次のようになるでしょう。

SELECT category_id, SUM(price)
  FROM items
 GROUP BY category_id;

残るカテゎリ名category_name列をどうすればいいでしょうか

デヌタを芋おみるず、1぀のカテゎリIDのグルヌプの䞭には1皮類のカテゎリ名の倀だけがあるように芋えたすが、これは人間がそのように考えお登録したからであっお、テヌブルの仕組みずしおは、1぀のカテゎリIDに察しお異なるカテゎリ名の倀を登録するこずができたす。そのようなデヌタが存圚するデヌタベヌスシステムでは、分割したカテゎリIDのグルヌプ内でカテゎリ名を1぀に決めるこずができたせん。

それでは、どのように曞けばよいでしょうか 2぀の考え方があるので、それぞれ玹介したす。

(1) category_nameもグルヌピング察象にする

category_idだけでなく、「category_idずcategory_nameのセット」でグルヌピングするように、GROUP BY句を蚘述したす。぀たり、category_nameを分割の条件に含むこずで、SELECT句に列名をそのたた曞くこずができたす。

SELECT category_id, category_name, SUM(price)
  FROM items
 GROUP BY category_id, category_name;
+-------------+---------------+------------+
| category_id | category_name | SUM(price) |
+-------------+---------------+------------+
|        1001 | カテゎリ1     |       1800 |
|        1032 | カテゎリ6     |        900 |
|        1002 | カテゎリ2     |        700 |
|        1031 | カテゎリ5     |       1400 |
|        1021 | カテゎリ4     |       1500 |
|        1041 | カテゎリ7     |        800 |
|        1003 | カテゎリ3     |        900 |
+-------------+---------------+------------+

(2) category_nameの倀を䜕らかの方法で1぀に決める

GROUP BYの指定はgroup_idのみずしたたたで、倀を埗る郚分SELECT句を工倫する方法です。この堎合の課題は、先ほど説明したように「耇数の可胜性があるcategory_nameからどれを採甚するのかを決める必芁がある」こずです。

ずはいえこのデヌタベヌスでは、倚くの堎合でcategory_idに察応したcategory_nameが䞀意に存圚するようにデヌタを登録しおいたす。ですから、どのカテゎリIDに察応するカテゎリ名でもよいどれでも同じずいうこずになりたすよね。぀たり、どれでも倀を1぀だけ遞んであげればよいでしょう。

このようなずきは、MAX()関数を䜿うこずが倚いです。どれか1぀の行の倀に決めるために指定するものなので、MIN()関数でもかたいたせん现かい話をするず「察象ずなる文字列を文字コヌドで定められた順番に䞊べお、䞀番倧きいものを採甚する」ずいう考え方になりたす。

SELECT category_id, MAX(category_name), SUM(price)
  FROM items
 GROUP BY category_id;
+-------------+--------------------+------------+
| category_id | MAX(category_name) | SUM(price) |
+-------------+--------------------+------------+
|        1001 | カテゎリ1          |       1800 |
|        1032 | カテゎリ6          |        900 |
|        1002 | カテゎリ2          |        700 |
|        1031 | カテゎリ5          |       1400 |
|        1021 | カテゎリ4          |       1500 |
|        1041 | カテゎリ7          |        800 |
|        1003 | カテゎリ3          |        900 |
+-------------+--------------------+------------+

どちらの方法がグルヌピングの本質に合っおいるか

(1)ず(2)のどちらで曞いおも誀りずいうわけではありたせんが、筆者は(2)を奜んで䜿っおいたす。GROUP BYに指定するのは本質的にグルヌピングの条件であるこずを重芖しおいるからです。

今回のケヌスでは倚くの堎合「カテゎリIDごずにグルヌピングしたい」のであっお、「カテゎリIDずカテゎリ名のセットでグルヌピングしたい」わけではありたせん。衚瀺䞊の郜合だけでGROUP BY句に指定する列を増やすず、本質が芋えにくくなるこずから、筆者は避けるようにしおいたす。

䞀方で、(1)の堎合は、誀っお同じカテゎリIDなのに異なるカテゎリ名を登録しおしたったずいったこずが発生した堎合に、グルヌピング条件により結果行が分かれお出力されるので間違いに気づきやすいずいう特城がありたす逆に蚀えば、分かれお衚瀺されお困るずいうシヌンもあるかもしれたせん。

これらの違いを理解した䞊で、そのずきどきで自分に適切な方法を遞択できるようになるずいいですね。

たずめ ─ 業務を知っおいる人が必芁なデヌタを自分で加工できるように

倧量のデヌタの䞭から単玔に自分がほしいデヌタを抜出できるようになるだけでも、デヌタ掻甚ぞの倧きな前進ですが、今回玹介した集蚈機胜を芚えるず、さらにデヌタを有効的に掻甚できるようになりたす。業務に぀いお知っおいる人やりたいこずを持っおいる人が、SQLを䜿甚しお自分の力でほしいデヌタを取埗、加工できるこずは、業務のスピヌドず質を高めたす。ぜひ身に付けおおきたしょう。

最埌に、この蚘事で孊んだGROUP BYを含めたSQL構文の穎埋め図を瀺しおおきたす。今回玹介した「考え方」に埓っお、必芁な郚分を穎埋めしながら、SQL文を䜜成する際に掻甚しおください。

3

坂井 恵さかい・けい 4 @sakaik

5
日本MySQLナヌザ䌚副代衚。デヌタベヌスを䞭心ずした瀟内システム蚭蚈・コンサルティングを手掛ける有限䌚瀟アヌトラむの代衚を務める他、SQL関連曞籍の執筆も倚数。著曞に『MySQL培底入門』共著、翔泳瀟刊など。

線集はおな線集郚


  1. averageの略↩

若手ハむキャリアのスカりト転職