DB?SQL?
久しぶりに記事書きます。
今回のテーマはDBやSQLについてです。
普段webのプロダクト開発をしていますが
非エンジニアの方からSQLについて質問される機会がそこそこあります。
例えば「SQLが合っているか」、とか「漏れている条件が無いか」などの質問が来ます。
そもそも、役割がきっちり分かれている会社だと
非エンジニアの方がSQLに関してあまりアンテナが立たないかと思いますが、
今勤めている会社ではどの職種の人でもデータを見る癖が付いているので
このような質問が来たりします。
なので、僕がエンジニアとして働いていてされた質問等を元に、以下のような悩みを持っている人の助けになればと思い、まとめてみました。
・SQLがデータを抽出する言語ということぐらいは知っているが、どのように書いたら良いかわからない。
・SQLやクエリという言葉は知っているが、実際にどんなものかあまりわかっていない。
こんな人が対象
PM、デザイナー、営業系の職種などの、非エンジニア、非アナリストの職種の方
SQLとは何か?
一言で言うと
「RDBMS(リレーショナルデータベースマネジメントシステム)と対話するための言語」です。
これで分かればもうこの先読む必要がないです。
では、RDBMSとは何かというところから解説していきます。
リレーショナルなデータベースを管理するシステムのことですが、
まずはデータベースが何なのかというところですね。
データベースとは?
データはデータベースという場所にあります。
なので、データベースとはデータを格納する場所のことですね。
例えばwebサイトだと、ユーザ登録ができる機能があると思います。
そこで登録したデータがデータベースに保存されていくというイメージです。
例:
ユーザ登録をする時に「名前、性別、住所」を入力した。
データベースには名前、性別、住所が保存される。
データベースにも種類がある
データベースには種類があります。
階層型、ネットワーク型、リレーショナル型、NoSQLとありますが、今最も使われているのがリレーショナル型になります。
リレーショナル型のデータベースが、リレーショナルデータベース(以下RDB)ということになります。
リレーショナル型?
リレーショナル型とは、行と列で構成された表によってデータを表現する方式になります。
RDBでは、表のことをテーブルと呼びます。
例えば、ユーザの名前と性別を保存しているテーブルが以下のようになります。
「ユーザの名前と性別」を保存しているテーブル
id | first_name | last_name | sex |
---|---|---|---|
1 | kenichi | matsuyama | 1 |
2 | haruna | kawaguchi | 2 |
まずfirst_name, last_nameという列を見ると
matsuyama kenichiさんという方と、kawaguchi harunaさんという方が登録されていることがわかるかと思います。
次にsexの列ですが、性別に関する列になります。
男、女、その他 というように保存しても良いのですが、
選択肢が絞られている場合は数字で表現することが多いです。
今回の場合は、「男:1」、「女:2」という表現にしています。
なので、matsuyama kenichiさんは男、kawaguchi harunaさんは女ということがわかります。
一番左のidというのはデータを一意に識別するための番号です。意味は特にありません。主キーと呼ばれるものですが、今は重要では無いので割愛します。
リレーショナルデータベースマネジメントシステムとは?
そして、こういった表を複数作り、それぞれを連結して管理することができます。
それがリレーショナルデータベースマネジメントシステム(以下RDBMS)です。
ただ、何でもかんでも表をつくれば連結出来るわけではありません(無理やりやろうと思えばできますが..)。
例として、先ほど作ったテーブルに関連しそうなテーブルを、もう一つ用意しましょう。
そして、表が複数あると判別しづらいので、名前を付けます。
「ユーザの名前と性別」を保存しているテーブル
名前:userテーブル
id | first_name | last_name | sex |
---|---|---|---|
1 | kenichi | matsuyama | 1 |
2 | haruna | kawaguchi | 2 |
「ユーザーの興味のある項目」を保存しているテーブル(←New!)
名前:user_interestedテーブル
id | user_id | web_industry | sports |
---|---|---|---|
1 | 1 | 1 | 0 |
2 | 2 | 0 | 1 |
user_interestedテーブルには、以下のようなデータが保存されています。
・userテーブルのid
・「web業界に興味がある:1, 興味がない:0」
・「スポーツに興味がある:1, 興味がない:0」
ここまで読んだ方はuserテーブルのid以外の意味はわかるかと思います。
このuserテーブルのidというのは、文字通り最初に作ったテーブルのidのことであり
紐づけることができます。
なので、2つのテーブルを連結すると以下のようなイメージになります。
2つのテーブルを連結した結果
id | first_name | last_name | sex | id | user_id | web_industry | sports |
---|---|---|---|---|---|---|---|
1 | kenichi | matsuyama | 1 | 1 | 1 | 1 | 0 |
2 | haruna | kawaguchi | 2 | 2 | 2 | 0 | 1 |
赤くした列が連結のために必要な、それぞれのテーブルで一致している情報ですね。
このようにして別々に保存しているデータを1つの表として集計することができます。
???「初めから1つのテーブルにしておけば良いのでは?」
という疑問もあるかと思います。その答えは一概にyes/noとは言えず、場合によります。
気になる方は正規化というキーワードで調べてみてください。
ただ、実務では基本的に複数のテーブルの情報を使って集計したいケースが多いかと思うので、このようなやり方を理解しておくことはとても重要になります。
ここまでがRDBMSについての説明になります。
RDB周りの用語
RDBに関してよく使われている用語が以下です。
エンジニアやアナリストが使っている言葉を理解するのに、最低限必要な用語かと思います。
行:レコード
列:カラム
表:テーブル
連結すること:ジョイン(なぜこう呼ぶのかは後述)
RDBにも種類がある
ここはあまり知らなくても良いですが、RDBにも種類があります。
代表的なのはmySQLとPostgreSQLです。
どのRDBかによって細かい違いがあったりするので、エンジニアレベルの知識を目指す方は知っておいても良いかと思います。
以下の記事がとても面白かったです(脱線)
https://employment.en-japan.com/engineerhub/entry/2017/09/05/110000
SQLとは
さて、ここまででデータベースやRDBについて何となく分かったかと思いますが、
SQLとはいわゆる言語。Structured English Query Languageの略です。
この言語を書いて、データを抽出するわけですね。
どのように抽出したら良いか、説明していきます。
SQLの構文
言語なので、構文がいくつかあります。
・データを抽出するための構文(SELECT文)
・データを更新するための構文(UPDATE文)
・データを挿入するための構文(INSERT文)
・データを削除するための構文(DELETE文)
この中で非エンジニアが必要とするのはSELECT文だと思います。
なので、今回はSELECT文についてのみ説明します。
SELECT文を書いてみる
では、連結する前のuserテーブルについて、kawaguchi harunaさんのデータを抽出してみましょう。
実際に正解を見てからの方が早いので以下に示します。
SELECT *
FROM user
WHERE first_name = "haruna"
これがSELECT文の標準的な例です。
これを実行すると以下の結果が得られます。
id | first_name | last_name | sex |
---|---|---|---|
2 | haruna | kawaguchi | 2 |
SELECT句
各句についてですが、まず「SELECT *」について。
ここは抽出結果のうちどのカラムを選択するかということを指定します。
「*」というのは全てを意味します。
なので、id, first_name, last_name, sexが結果で得られています。
指定する場合は以下のようにします。
SELECT id, last_name
FROM user
WHERE first_name = "haruna"
結果は以下のようになります。
id | last_name |
---|---|
2 | kawaguchi |
FROM句
FROM句は、テーブルを指定するために記述します。
FROM user
とするとuserテーブルを指定することになります。
user_interestedテーブルを指定したい場合は以下のように書き換えれば良いです。
FROM user_interested
WHERE句
WHERE句は検索条件を指定します。
今回はkawaguchi harunaのレコードを探したかったので、first_nameがharunaのレコードを条件に入れました。
しかし、これだと「kondoh haruna」さんというレコードがあった場合にヒットしてしまいます。
なので、そう言う場合は複数条件を指定することで確実に抽出することができます。
SELECT id, last_name
FROM user
WHERE first_name = "haruna"
AND last_name = "kawaguchi"
※実際の現場では同姓同名のレコードがある場合もあると思うので、そういった考慮もする必要があります。
テーブルを結合してみる
ここまでで単一テーブルからのデータ抽出の仕方を学ぶことができました。
それでは最後に他のテーブルと結合する時の書き方を学びましょう。
SELECT *
FROM user
JOIN user_interest ON user.id = user_interest.user_id
新しくJOINという句が出てきました。
まずFROMにuserテーブルが指定され、それと結合したいuser_interestテーブルをJOINの後に記述します。
JOIN user_interest
そして、どのカラム同士を紐づけるのかを指定しているのがONの後です。
ON user.id = user_interest.user_id
これで以下の結果が得られます。(先ほどと同じ)
id | first_name | last_name | sex | id | user_id | web_industry | sports |
---|---|---|---|---|---|---|---|
1 | kenichi | matsuyama | 1 | 1 | 1 | 1 | 0 |
2 | haruna | kawaguchi | 2 | 2 | 2 | 0 | 1 |
応用でWHERE句を一緒につけることもできます。
SELECT *
FROM user
JOIN user_interest ON user.id = user_interest.user_id
WHERE user.sex = 1
結合した後、性別が男のレコードのみ抽出というSQLになります。
id | first_name | last_name | sex | id | user_id | web_industry | sports |
---|---|---|---|---|---|---|---|
1 | kenichi | matsuyama | 1 | 1 | 1 | 1 | 0 |
実行する時の注意点
さて、ここまでで簡単ではありますがDBとは〜SQLまでの説明をしてきました。
実務で使う場合の参考になれば幸いです。
ただし、使う前に以下のような注意点を頭に入れておいていただけると、安全かと思います。
・基本はプロに任せる
→プロに任せた方が正確かつ、安全です。慣れないうちは仕事を奪ってまで自分で書こうとするのではなく、任せた上でどんなSQLを書いているのかを見て学ぶのが良いと思います。
・書いたら実行する前にプロにチェックしてもらう。
→慣れてきてもその実行で何が起きるか分からないので、必ずダブルチェックをしてもらった方が良いと思います。
・広すぎる条件で実行しない
上記とも被りますが、
大量のレコードを保存しているテーブルにWHERE句を指定せずに実行すると処理がとても重くなります。
なるべく条件を指定するようにしましょう。