8
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

非エンジニアのSQL入門

Last updated at Posted at 2020-02-24

最近、社内でエンジニア以外の方へSQLを教える機会があり、そこだけの話にするのはもったいないと思ったのでqiitaにまとめてみました。

はじめに

データドリブンと言われるようになって久しい今日この頃、営業や企画など非エンジニアの方もSQLを駆使してデータを取得している場面をよく目にするようになりました。
ただ、SQLとかデータベースとかハードルが高いよ!と感じている方も多いと思います。
しかしデータを参照するためのSQLだけであればすごく簡単に習得できるので是非チャレンジしてみてください。

なお、この記事ではデータ参照のみを扱います。また参照の中でも使用頻度が高いと思われるもののみ扱います

前提条件

  • SQLを実行してデータを取得できる環境があり、アクセスできること
    • そもそもデータベースを使っていない場合は対象外です
    • データドリブンを掲げているのであれば参照専用の環境はあるはず
  • SQLを毎回書いてデータを取得するのはアドホックなデータを取得したい時です
    • 定型データの抽出はミスなく簡単に取得できるようにシステム化してもらいましょう

データについて

データは「テーブル」と呼ばれる箱に入っています。
テーブルは「カラム」と呼ばれるデータ項目を持っています。
Excelなどの表を想像するとよいかもしれません。

テーブルの具体例

文章だけではわかりづらいので具体例を挙げます。
ユーザー情報、試験情報、ユーザーが受験した試験情報の3つのテーブルを使います。

ユーザー情報を持っているテーブル「users」

ユーザー情報は「id(一意に識別するための番号)」、「name」、「email」を持っているものとする

id name email
1 伊藤一郎 ito1@example.com
2 伊藤次郎 ito2@example.com
3 鈴木太郎 suzuki@example.com
4 佐藤花子 sato@example.com

試験情報を持っているテーブル「exams」

試験情報は「id(一意に識別するための番号)」、「name」を持っているものとする

id name
1 国語
2 数学
3 物理
4 化学

ユーザーが受験した試験情報を持っているテーブル「user_exams」

ユーザーが受験した試験情報は「exam_id(受験した試験のid)」、「user_id(受験したユーザーのid)」、「point」を持っているものとする

exam_id user_id point
1 1 100
1 2 90
1 3 65
1 4 70
2 1 100
2 2 60
2 3 95
2 4 80
3 1 100
3 3 60
4 1 100
4 2 55
4 4 80

このテーブルは急に数字だらけになってしまいわかりづらいと思うので、このテーブルから読み取れることをいくつか列挙しておきます。
下記のことがテーブルから読み取れることを確認してください。

  • 国語、数学の試験は4人全員が受けている
  • 物理は伊藤一郎と鈴木太郎の2人が受けている
  • 伊藤一郎は4科目受けており、全部100点

データ抽出のSQLについて

ここからデータ抽出のSQLについて書いていきます。

データ抽出SQLの基本形

1テーブルからデータを取得するSQLは下記の構文で記載できます。

select
  [参照したいカラム1, 参照したいカラム2, ...]
from
  [テーブル名]
where
  [抽出条件]

[参照したいカラム]には、参照したいデータのカラム名記載します。
複数ある場合はカンマ区切りで書きます。

[テーブル名]には参照したいカラムを持っているテーブル名を記載します。

[抽出条件]には取得したいデータの条件を記載します。抽出条件は具体例を説明する時に一緒に説明します。

これまた具体例がないとわかりづらいと思うので具体例を挙げます。

ユーザー情報を全部取得

select
  id, name, email
from
  users

全件取得の場合は抽出条件は省略できるのでwhereは書いていません。

  • 取得結果
id name email
1 伊藤一郎 ito1@example.com
2 伊藤次郎 ito2@example.com
3 鈴木太郎 suzuki@example.com
4 佐藤花子 sato@example.com

今回は明示的にカラムを指定しましたが、fromに指定したテーブルの全カラムが欲しい場合は*で指定することもできます。

select
  *
from
  users

こちらでも1つ前のSQLと同じ結果が得られます。

逆にemailとnameだけ欲しいという場合は下記のように書きます。

select
  email, name
from
  users
  • 取得結果
email name
ito1@example.com 伊藤一郎
ito2@example.com 伊藤次郎
suzuki@example.com 鈴木太郎
sato@example.com 佐藤花子

※指定したカラムの順序も結果に反映されます。

特定のユーザー情報を取得

鈴木一郎のユーザー情報を取得する場合

select
  id, name, email
from
  users
where
  name = '伊藤一郎'

このように任意のカラムが特定の値のデータが欲しい場合はwhere[カラム名] = [値]で指定できます。
今回は鈴木一郎の情報だけ必要なので、wherename = '鈴木一郎'と書いています。
ちなみに値は'で囲ってください。

  • 取得結果
id name email
1 伊藤一郎 ito1@example.com

特定のユーザー情報を取得(複数)

先ほどの例では値を1つ指定していましたが、複数指定することもできます。
伊藤一郎と鈴木太郎のユーザー情報を取得する場合

select
  id, name, email
from
  users
where
  name in ('伊藤一郎', '鈴木太郎')

複数指定する場合は[カラム名] in ([値1], [値2], ...)で指定できます。
inの中のいずれかに一致するデータを取得できます。

  • 取得結果
email name
ito1@example.com 伊藤一郎
suzuki@example.com 鈴木太郎

部分一致しているユーザー情報を取得する

伊藤という苗字のユーザー情報を取得する場合

select
  id, name, email
from
  users
where
  name like '伊藤%'

[カラム名] like [値]で部分一致で検索することができます。
likeを使用すると、値の中に%(ワイルドカード)を使用することができるようになります。
例の場合は最後に%をつけているので'伊藤'で始まるユーザー情報が取得できます。
また最後が'一郎'で終わるユーザー情報を検索する場合は%一郎のように前に%をつけることで検索できます。
また'藤'という漢字を含むユーザーを検索する場合は%藤%のように前後に%をつけることで検索できます。

※※※注意※※※
likeを使った部分一致検索はとてもパフォーマンスが悪いためデータ量が多い場合、データ抽出にかなりの時間がかかる可能性があります。
(likeに限らずですが)そういった事象に遭遇した時はSQLに詳しい方に相談してください。

  • 取得結果
email name
ito1@example.com 伊藤一郎
ito2@example.com 伊藤次郎

複数カラムの条件指定

user_examsから国語(exam_id=1)で80点以上のユーザーIDを取得する場合

select
  user_id, point
from
  user_exams
where
  exam_id = 1
  and point >= 80

条件に複数のカラムを指定する場合はandを使います。andを使うことで全ての条件を満たすデータを取得できます。
数値データの場合は'で囲む必要はありません。
値の比較に不等号を使うこともできます。具体例は下記の通り。

where 抽出できるデータ
point = 100 100点のデータ
point >= 50 50点以上のデータ
point > 50 50点より高いデータ
point <= 50 50点以下のデータ
point < 50 50点より低いデータ
point <> 100 100点以外のデータ
  • 取得結果
user_id point
1 100
2 90

ユーザーID1,2のユーザーが国語で80点以上をとったということがわかりました。
ただ、よくあるユースケースではユーザーIDだけではなく名前も欲しくなりますよね?
追加でusersからid in (1, 2)と検索することで取得できますが、人数が多いと大変なのでもっと手軽に取得したいですよね。
ということで次は複数のテーブルからデータを取得する方法を説明します。

複数テーブルからデータ抽出

複数のテーブルを結合することで各テーブルの情報をまとめて取得することができます。

テーブル結合の構文

fromのところで結合したいテーブルをinner join [テーブル名] on [結合条件]で指定します。

select
  [参照したいカラム1, 参照したいカラム2, ...]
from
  [テーブル名]
  inner join [結合テーブル1] on [結合条件]
  inner join [結合テーブル2] on [結合条件]
  ...(結合したいテーブルの数だけ記述)
where
  [抽出条件]

結合条件にはレコードを結合する条件を書きます。
例えばusersとuser_examsでは、users.idとuser_exams.user_idが同じユーザーのことを示しているので下記のように指定します。

from user_exams
  inner join users on users.id = user_exams.user_id

上記のように結合させると結合後のテーブルは次のようなイメージになります。

user_exams.exam_id user_exams.user_id user_exams.point users.id users.name users.email
1 1 100 1 伊藤一郎 ito1@example.com
1 2 90 2 伊藤次郎 ito2@example.com
1 3 65 3 鈴木太郎 suzuki@example.com
1 4 70 4 佐藤花子 sato@example.com
2 1 100 1 伊藤一郎 ito1@example.com
2 2 60 2 伊藤次郎 ito2@example.com
2 3 95 3 鈴木太郎 suzuki@example.com
2 4 80 4 佐藤花子 sato@example.com
3 1 100 1 伊藤一郎 ito1@example.com
3 3 60 3 鈴木太郎 suzuki@example.com
4 1 100 1 伊藤一郎 ito1@example.com
4 2 55 2 伊藤次郎 ito2@example.com
4 4 80 4 佐藤花子 sato@example.com

user_examsに結合条件であるuser_exams.user_idとusers.idが一致するレコードがくっつくイメージです。

users, user_exams, examsの結合

先ほどの例と同じでuser_examsから国語(exam_id=1)で80点以上のユーザーIDを取得する場合を考えます。
今回はユーザー名が知りたいのでusersテーブルを結合します。ついでに試験名も取得するためにexamsも結合します。

select
  users.id, users.name, user_exams.point, exams.name
from
  user_exams
  inner join users on users.id = user_exams.user_id
  inner noin exams on user_exams.exam_id = exams.id
where
  user_exams.exam_id = 1
  and user_exams.point >= 80

1テーブルの時と違い、カラム名に[テーブル名].をつけています。
1テーブルの場合はテーブル名を指定しなくてもどのテーブルのカラムかわかるので省略できるのですが、複数テーブルある場合は同名のカラムがある可能性があるのでテーブル名を指定します。
ということなので、どのテーブルとも被っていないカラムはテーブル名は省略可能です。ただ、最初のうちはわかりやすさのためにもテーブル名は指定するものと覚えても良いかもしれません。

抽出結果は下記の通り

users.id users.name user_exams.point exams.name
1 伊藤一郎 100 国語
2 伊藤次郎 90 国語

並び順

抽出するデータの並び順を指定することができます。
下記のようにorder byで指定します。

select
  [参照したいカラム1, 参照したいカラム2, ...]
from
  [テーブル名]
where
  [抽出条件]
order by
  [ソートカラム] [ソート条件], [ソートカラム2] [ソート条件],...

例えばuser_examsで点数の高い順に並べたい場合は下記のように書きます。点数が同点の場合はuser_idの昇順にします。
ソートカラムに指定した1つ目のカラムで並び替えますが、もし同じ値の場合は2つ名のソートカラムでさらに並び替えます。もしそこも同じ値であれば3つ目のソートカラム、いうように同値がある限り次のソートカラムを参照して並べようとします。
もし同じ値があるのに次のソートカラムが指定されていない場合は取得順は不定になります。

select
  exams_id, user_id, point
from
  user_exams
order by
  point desc, user_id asc

ソート条件に指定しているdescは降順を指定しています。ascは昇順です。
このSQLを実行すると下記のように出力されます。

exam_id user_id point
1 1 100
2 1 100
3 1 100
4 1 100
2 3 95
1 2 90
2 4 80
4 4 80
1 4 70
1 3 65
2 2 60
3 3 60
4 2 55

point=100のデータは全てのuser_id=1であり、orderで指定されたカラムだけでは順番が確定できないので、順番は不定になります。
もし順番を確定させるのであれば、ソートカラム3にexam_idを指定するなどして順番が確定するようにします。

集計

SQLではデータ数などの集計情報を取得することができます。
集計を詳しく説明するととても複雑なのでここでは単純なデータ数の取得だけ触れることにします。興味がある方は別途調べてみてください。

データ数をカウントする

データ数をカウントします。例えばuser_examsで80以上のデータ数をカウントする場合は下記のSQLを書きます。

select
  count(*)
from
  user_exams
where
  point >+ 80

結果は下記の通り

count(*)
8

最後に

なんやかんやで長くなってしまいましたが、単純に抽出するだけのSQLであれば比較的簡単に理解できたと思います。
できる限り具体例を交えて説明しましたが、習得するには実践あるのみだと思いますのでガンガンSQLを使っていってください。
簡単に書いたつもりではいるのですが、SQLを知っている人(私)が書いているので知らない人には意味がわかりづらい表現もあると思います。
そういうところはぜひコメントなどしていただければと思います。
できる限り改善したいと思います!

この記事では基本的なことしか書いていません。SQLでデータ抽出をよくやるようになると書いてあることだけではできない様々な抽出をやりたくなると思います。
そうなったときにはすでにSQL初心者は脱していると思うので、次のステージへステップアップしていってください!

8
8
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
8
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?