私事ながら25年4月をもって大学を卒業し社会人になりました。
新卒研修の中にSQL
がありまして、ワタクシは一応経験者なのでヌルッと終えたのですが、宇宙猫みたいになってる同期もいた気がしました。
もちろん研修はとっても分かりやすくてサポートもしっかりしてくれてました。
でもでも〜、やっぱり〜、難しいんだよな〜。
当然です、総合職採用の人も研修に参加しているのですから。
人生初プログラミング言語がSQL
って、人生初遊園地で富士急行くみたいな感あります。(知らんけど)
そこで、「僕的こう理解したら分かりやすいポイント」を共有したいと思います。
ディティールは端折っているので悪しからず。
まず、SQLとは何か
SQL
、それは知識
です。
我々人間、生きていたら覚えておきたいものができますよね。
こんな感じに。
明日会社に行く
会議に参加(8:00)
部長と12時に面談
でも、これだとちょっと見にくいですね。
時間とやることがバラバラです。
こんなふうにしてみましょう。
|番号|時間|やること |
===================
|① |明日|会社に行く|
|② | 8時|会議に参加|
|③ |12時|部長と面談|
いいですね。
情報が整理されて見やすくなりました。
誰かと共有するときも「②の時間だけど変更できる?」と明確に話すことができます。
これが人間の獲得した「表」という素晴らしい仕組みです。
そして、この「表」という仕組みはシステムの世界でも大変有効です。
システム的にタスクの時間を取得することを考えましょう。
知識 Lv.1
から時間を取得するためには、テキスト検索などが必要になり難易度が高そうです。
一方、知識 Lv.2
では「2列目」と表現できるので簡単そうですね。
この仕組みを積極的に活用していくために使うのがSQL
です。
なぜSQLなのか
知識を扱うのに表形式が便利だって?
そんなことは分かってるよ!だってExcel
使ったことあるもん!
そうです。
我々には慣れ親しんだExcel
という、表を扱う大変使いやすいツールがあります。
なのに、何故あれほど難解なプログラミングをせねばならないのでしょうか。
それは、Excel
が使いやすいからです。
使いやすいから…、使えない…?
使いやすいというのはどういうことでしょうか。
よく分からない文字列を打ち込まないでよく、目で見てマウスで操作できるってことです。
この見て操作できるシステムをGUI
といいます。
逆に、文字列を打ち込んで操作しないといけないシステムをCUI
といいます。
さて、このGUI
、重いんです。
なぜ重いのかというと、パソコンの中がこんな仕組みになっているからです。
[CUI]
難解な文字列の指示
人間 <--------------------------------------------> システム
[GUI]
マウスなど視覚情報 難解な文字列の指示
人間 <----------------> 通訳マン <-----------------> システム
この翻訳が結構大変なんです。
GUI
はシステムとの会話を人間が理解しやすい視覚情報に翻訳してくれているから重いんですね。
でも、
Excel
って重くないよ?
ええ、そうなんです。
そうなんですが、会社とかで扱うデータって、それはもう膨大な量なんです。多分。
ウン十万、ウン百万、ウン千万というデータを扱います。
そうすると流石のExcel
も音を上げます。
それに、そんなたくさんの行をドラッグしたりって大変ですよね。
そこで出てくるのがSQL
です。
CUI
であるSQL
は軽くて、速いのです。
もちろん、それだけじゃなくって、他のシステムから使いやすかったり、複雑な処理ができたり、整ったデータを作れたり、色々といいことがたくさんあります!
では、どのように使うのか
SQL
は言語ですので、SQL
を書きます。
そしてそれを実行します。
「パパー、リモコンとって〜」
これは日本語です。
リモコンを取る
という指示をパパ
で実行できますね。
SQL
も同じです。
この指示が「クエリ」というやつです。
ただし、パパが活動しているのは家の中ですが、SQL
が活動するのはデータベースという世界になります。
データベースの世界では少し細かく指示をしないといけません。
まず、リモコンはどこにあるのでしょうか?
ここでは机の上としましょう。
select リモコン from 机;
パパ(SQL)は頑張ります。
パパの返答は?
リモコン |
---|
テレビ |
エアコン |
照明 |
これはまずいです。
机の上にはたくさんリモコンが置いてありました。
なんのリモコンを取って欲しいかも指示しないといけませんでしたね。
select リモコン from 机 where リモコン = テレビ;
パパは再び頑張ります。
リモコン |
---|
テレビ |
無事にテレビのリモコンが手に入りました。
喜ぶのはまだ早い
先ほどのデータベースには問題があります。
次の場合にどうやって対応するでしょうか。
「パパー、ティッシュ取って」
「パパー、スマホも〜」
select ティッシュ from 机;
パパ「ティッシュ…?」
そうです。
リモコンデータベースにはティッシュという列は存在しません。
ティッシュデータベースに聞かないといけないですね。
でも、ティッシュにスマホ、新聞も…、全部別のデータベースにしたら大変です。
「パパ、ティッシュが欲しいんだけど、ティッシュの情報が載っているのはどのデータベース?」
「うーん、ティッシュデータベースだね」
「じゃあティッシュデータベースからボックスティッシュを取って欲しいな」
「よし分かった、今からティッシュデータベースを開くからちょっと待っててね」
「パパー、鼻水垂れちゃうよぉ…」
どうすれば良いのか
取って欲しいものを全て同じデータベースにまとめておけば便利そうですね。
ついでに、机の上のものだけじゃなくて、部屋中のものをまとめておけば更に便利そうです。
そうすると列の名前も変わりそうですね。
番号 | 種類 | 追加情報 | 場所 |
---|---|---|---|
1 | リモコン | テレビ | 机 |
2 | リモコン | 照明 | 机 |
3 | リモコン | エアコン | 机 |
4 | ティッシュ | ボックス | 机 |
5 | ティッシュ | ポケット | カバン |
6 | スマホ | 娘の | ソファ |
7 | 新聞 | NULL | 床 |
8 | スマホ | パパの | 机 |
いい感じです。
こうすると、各列が「情報の種類」を示し、各行が「もの自身」と紐つくことになります。
これがリレーショナルデータベース
というシステムの基本的な構造になります。
何かを取って欲しいときには次のように言えばいいですね。
select * from 部屋 where 種類 = リモコン and 追加情報 = テレビ;
select * from 部屋 where 種類 = スマホ and 場所 = ソファ;
パパ、またまた頑張ります。
ちなみに*
は全てという意味で、この場合は該当する行を一行分取得することになります。
番号 | 種類 | 追加情報 | 場所 |
---|---|---|---|
1 | リモコン | テレビ | 机 |
6 | スマホ | 娘の | ソファ |
テレビのリモコンも、机の上のスマホも、上手に取ってもらうことができましたね!
つまり?
つまり、SQL
の使いやすさはデータベースの設計次第ということです。
そして、どんな指示を出すべきか、それもデータベースの設計次第です。
最も重要なこと
以上のことを踏まえると、SQL
を学ぶために重要なことが見えてきます。
SQL
とは、表として整理された情報を操作する言語です。
記述する時はデータベースの構造を理解することが大切です。
SQL
の表は情報の種類を表す「列」と、個々のデータである「行」で構成されます。
基本的には運用中に列が変化することはありません。
ある行の3列目には「追加情報」が、違う行の3列目には「重さ」が、と言うように、同じ列に違う種類の情報が混在していたら困りますよね。
運用中に起こる変化は、行が増える、行が減る、行が書き換えられる、ということになります。
ちなみに、運用というのは部屋の例で言えば「生活」です。
そこで起きる変化は「新しくタブレットを買った」とかです。
その場合、部屋のものデータベース
にはタブレットの行が増えることになりますね!
SQL
の表は「テーブル」と呼ばれます。
部屋の例ではデータベースと呼びましたが、正しくは「部屋のものテーブル」です。
表=テーブル
です。
データベースというのは、広義では「情報を保存しておく場所」という概念であり、狭義ではリレーショナルデータベースにおける「複数のテーブルの集合」です。
後者のイメージは、「家」というデータベースがあり、その中に「リビングのものテーブル」「パパの部屋のものテーブル」「玄関のものテーブル」があるような感じです。
テーブルは、最低一つの、各行が一意となる値の列を持ちます。
「各行が一意となる値の列」とはなんでしょうか?
これはプライマリーキー
と呼ばれ、部屋のものテーブル
では「番号」の列に相当します。
一意となる、とは「そのテーブル全ての行について重複のない」ということです。
番号が3の行といえば「机にあるエアコンのリモコン」の行しかありませんよね。
行を指定して書き換えたり削除するために必要となるので、テーブルは必ずプライマリーキー
を持ちます。
概ね、プライマリーキー
に使用される値は通しの番号だったりuuid
という長い文字列だったりします。
多くの場合、一つのデータベースには複数のテーブルが存在します。
「家」というデータベースがあり、その中に「リビングのものテーブル」「パパの部屋のものテーブル」「玄関のものテーブル」がある
テーブルを分けておくと色々と便利なことがあります。
例えば、SNSでユーザーを管理するデータベースを考えましょう。
あるテーブルA
には「ユーザーのアカウント名」「ユーザーのアイコン」などを登録しておきます。
違うテーブルB
に「ユーザーのパスワード」を保存しておきます。
また違うテーブルC
に「ユーザーの投稿内容」を保存しておきます。
こうすることで、どんないいことがあるでしょうか?
テーブルC
は色んな人が読み書きをしそうですよね。
投稿をしたり、投稿を見たり、投稿を書き換えたり…。
でもテーブルA
はどうでしょうか?
色んな人が読み取りするのは問題ないですが、書き込みはちょっと慎重になりますよね。
やたらめったら削除されたり、アカウント名を適当に変更されたら困ります。
そしてパスワードが保存されているテーブルB
は読まれたら困りますよね。
なんとしても秘密にしておきたいです。
これを一つのテーブルに保存しておいたら管理が大変そうですよね。
テーブルを分けることでテーブルごとに権限とかを設定できます。
エクセルで言うと、ファイルを分けておけば「これは見ていいけどこっちはダメ」みたいに管理できるよねって話です。
よし分かった、それで、どうやって使うの?
実際のSQL文
はAI
に聞いたりググったりするのが早いです。
代表的なものだけ紹介します。
基本のき
改行と二つ目以降の空白は意味を持ちません。
次の三つは同じ意味になります。
select * from hoge;
--------------------
select
*
from
hoge;
--------------------
select * from hoge;
でも、むやみやたらに改行したりするのはやめましょうね。
型
プログラミングの世界では「型」というものがあります。
これは、「あらかじめ種類を決めておく」と覚えておくといいでしょう。
病院に来る患者さんの型は「人間」です。
そこに違う型の「動物」が来たら困りますよね。
あるいは、型が決まってなくて「人間」と「動物」が一緒に来ても困りますよね。
プログラムも同じです。
数字が来るだろうと処理を進めていて文字が来たら困るのです。
だから、あらかじめ型というデータの種類を決めておいて、処理が円滑に進むよう工夫しているのです。
SELECT
先ほどから何度も出てきていますね。
情報を取ってきて〜ってやつです。
select row_name from table_name;
取得したい列名
と取得したいテーブル名
を指定します。
FROM
どんなクエリでもほぼ必ず使うFROM
ですが、本棚と机を想像するといいと思います。
いろんなテーブルが入っているデータベースから、これから作業するテーブルを指定するコマンドになります。
本棚から、本(テーブル)を取り出して、机に広げてね!という指示になります。
SELECT
次は広げた本(テーブル)から任意の列を取り出していきます。
select 住所 from table_name;
これだとたくさんの行が返ってきてしまいます。
なのでLIMIT
を使ったりします。
急に「リモコン53万個も取って!」とか言われたらパパも困っちゃいますからね!
ORDER BY
一番年齢が若い人の住所が欲しい時とかには並べ替えをします。
select 住所 from table_name order by 年齢 asc;
由来は英単語です。
ASCending : 上昇
DESCending : 下降
昇順は進むにつれ昇っていくので、一番最初は一番小さくなりますね。
A->Z
も昇順です。
WHERE
田中さんのデータが見たい!という時はどうすればいいでしょうか。
select * from table_name where '名前' = '田中';
これで名前列の値が「田中」の行が全て選択できます。
等号不等号いろいろな比較演算子で検索できます。
GROUP BY
任意の列が同じ値の行をグループ化してくれます。
番号 | 種類 | 追加情報 | 場所 |
---|---|---|---|
1 | リモコン | テレビ | 机 |
2 | リモコン | 照明 | 机 |
3 | リモコン | エアコン | 机 |
4 | ティッシュ | ボックス | 机 |
5 | ティッシュ | ポケット | カバン |
6 | スマホ | 娘の | ソファ |
7 | 新聞 | NULL | 床 |
8 | スマホ | パパの | 机 |
例えば、上のテーブルがあるときに「物がおいてある場所を全部知りたい」みたいな時。
select 場所 from 部屋 group by 場所;
場所 |
---|
机 |
カバン |
ソファ |
床 |
注意点は、GROUP BY
を使ったら「グループ化した列」と「関数の結果」しか取得できないということです。
なぜでしょうか。
GROUP BY 場所
の後を考えてみましょう。
場所でグループ化するので次のようになりますね。
番号 | 種類 | 追加情報 | 場所 |
---|---|---|---|
1,2,3, 4,8 |
リモコン,リモコン, リモコン,ティッシュ, スマホ |
テレビ, 照明, エアコン, ボックス, パパの | 机 |
5 | ティッシュ | ポケット | カバン |
6 | スマホ | 娘の | ソファ |
7 | 新聞 | NULL | 床 |
当然ですがGROUP BY
をすると、グループ化に使った列以外は、複数の行の値がごちゃ混ぜになってしまうのです。
こうなると、机行
の番号
や種類
、追加情報
の値は意味をなさなくなっていますね。
パパも「追加情報はテレビ, 照明, エアコン, ボックス, パパの
だよ!」って言われても困ってしまいます。
--これはエラーになる
select 追加情報 from 家 group by 場所;
では関数はどうでしょうか。
例えばCOUNT関数
です。
「パパ、追加情報
の数は5個だよ!」
これは良さそうですね。
--これはOK!
select 場所, count(追加情報) from 家 group by 場所;
まとめ
元気があれば他の句とか続きを書きます。
プログラミングの心構えは「エラーは先生、友達」です。
エラーをよく読むことはとても大切です。
そして、仕組みの裏側を知れるときっと成長すると思います。
なんでこれを使うのか、なんでダメなのか、そういうことを考える姿勢を持てるといいですね。
僕も持ち続けたいです。
致命的に間違っているところがあれば教えてください。
いいねしてもらうと僕が喜びます。
拙い文章ですが最後まで読んでいただいてありがとうございました!