はじめに
WEB制作をしているとSQLという単語をよく見かけるかと思います。
代表的なところで言えばMySQLがまさにそうでしょう。
SQLとはStructured Query Languageの頭文字を取ったもので、データベースの操作で使われます。
たとえばデータベースに保存された値の取得と更新、登録、削除は全てSQLによる指示に従って実行されています。
WordPressやPHPのフレームワークであるLaravelなどは、それぞれの仕様に従ってSQLを操作しやすくされており、WordPressであればget_title()やget_content()、LaravelであればEloquentがそれに該当します。
WordPressをノーコード、ローコードでしか触ったことのない人には馴染みがないかもしれませんが、何かを介する形で、知らないうちにSQLを操作していたのです。
ですがこれらにも欠点があります。
それはSQLの最適化(チューニング)が難しい、またはできないということです。
SQLは1つの結果を求めるために複数の指示方法があり、命令文が冗長(無駄に長い)だったり複雑な条件であるほど実行速度が低下してしまいます。
では実行速度が低下しやすい命令文を簡素にするにはどうすれば良いか?
答えは簡単です。
自分で最適化(チューニング)してしまえば良いのです。(ある意味パワープレイ)
先ほど例に挙げたget_title()程度ではチューニングするほどでもないですが、wp_queryには自分で複数の条件をつけて記事を絞り込むことができます。
カスタムフィールドの値を条件に加えるとき。
もしくはwp_query単体だけでは実現できない絞り込み条件のとき。
その分、記述量は増え、相対的に実行するSQLはより長くなってしまいます。
さて、こんなときにチューニングができればどうでしょう?
ゼロコンマの違いしかないかもしれませんが、WEBの世界では1秒以下の秒数を少しでも削ろうとすることがままあり、このようなときにWordPressが用意している関数を利用せず、その時々の条件に最適化されたSQLを書くことで処理速度を少しでも早めることができます。
さて、前置きが長くなってしまいましたが、次からSQLの入門編を始めていきます。
データベースとは?
データベースとは謂わば情報の集合体です。
そのなかにはテーブルと呼ばれる格子状の表に一定の規則で情報が整理されています。
とは言ってもこれでは何が何やらという感じですね。。。
私がよく例え話で使うのが、「データベースがエクセルファイル、テーブルがシート」です。
テーブル(シート)は1行=1件分の情報が上から下にズラッと並べられており、これはテーブルごとに設定された規則に則っています。
例えば都道府県が1行ごとにまとめられたprefテーブル、市区町村が1行ごとにまとめられたcityテーブルなどです。
そしてこれらのテーブルがまとまったのがデータベース(エクセルファイル)です。
ちなみに、さくらレンタルやロリポップ、エックスサーバーなどのレンタルサーバーではデータベースを人がわかる形で整えたphpMyAdminが使えます。
もしレンタルサーバーを契約していたら是非phpMyAdminを見てください!
SQLの命令
ではここから、実際のSQLを見ていきましょう。
PHPやJavaScriptなどとは書き方が異なるため、馴染みがないのも合わさって最初は意味不明な文字列にしか見えないでしょう。
ですが語句を1つ1つ理解できれば、そこまで難しくもありません。
もちろん、上級仕様に書かれたSQLなんて未だに私も意味不明な文字列にしか見えませんが。
呼び出し
まずは基本の呼び出しからです。
呼び出しは既にデータベースに保存されている情報を引き出します。
その際に、絞り込むための条件やグループ化などができます。
標準
SELECT * FROM 従業員表
SELECT ○○ で呼び出す値に対応したカラムを指定します。
ここでは*(アスタリスク)
が記述されていますが、これは全てのカラムを意味します。
続けて FROM テーブル名 でどのテーブルから呼び出すかを指定しています。
つまり、このSQLは従業員表というテーブルから、全てのカラムに属する情報を呼び出しているのです。
ちなみに、条件などを付けなかった場合は基本的に全てのレコードを呼び出します。
呼び出すカラムを指定
SELECT 社員番号, 部署名, 氏名 FROM 従業員表
先ほどは全てのカラムを呼び出すためにSELECT *
としましたが、呼び出したいカラムが定まっているのであれば,(カンマ)
カラムを区切って指定することができます。
ここでは従業員表から、社員番号、部署名、氏名だけに絞られた全レコードが呼び出されます。
条件
SELECT * FROM テーブル名 WHERE 条件式
SELECT〜テーブル名
までは上記と同じですがWHERE句
を加えることで、そのあとに続けて絞り込むための条件を加えることができます。
以下は条件の一例です。
なお、条件はif文
などと同じように条件式を記述します。
等号・不等号
SELECT * FROM 従業員表 WHERE 給与 >= 250000
WHERE句
の条件式は給与 >= 250000
となっており、給与の値が250,000以上のレコードのみが呼び出されます。
範囲
SELECT * FROM 従業員表 WHERE 給与 >= 180000 BETWEEN 給与 <= 210000
BETWEEN句
は前後の条件式に合致するレコードだけを絞り込みます。
ここでは給与が180,000以上、210,000以下のレコードが対象です。
論理式との組み合わせ
SELECT * FROM 従業員表 WHERE 性別 = '男' AND 年齢 >= 20 OR 身長 >= 170 BETWEEN 身長 < 180
条件式はこのようにANDやORなども組み合わせて、複雑な条件式を記述することもできます。
この例はちょっと条件が多いので、分割して説明します。
まずはこのSQLを簡単に見てしまえば、SELECT * FROM 従業員 WHERE 条件式
となっているのがわかります。
WHERE句以前は前述の全てのレコードを呼び出しています。
ではWHERE句より後の条件式はどうなっているでしょうか。
WHERE句以降の性別 = '男' AND 年齢 >= 20 OR 身長 >= 170 BETWEEN 身長 < 180
は、性別 = '男' AND 年齢 >= 20
OR 身長 >= 170 BETWEEN 身長 < 180
と分けられます。
ここでちょっとだけ解説をはさみますが、初めて出てきたANDとORが何かわかりますか?
PHPで例えれば、ANDは条件式の&&、ORは同じく||のことです。
つまりここで分けた2つの条件式のどちらかに当てはまれば良いわけです。
では1つ目の性別 = '男' AND 年齢 >= 20
は性別が男かつ年齢が20歳以上。
2つ目の身長 >= 170 BETWEEN 身長 < 180
は身長が170cm以上、180cm未満の範囲に当てはまるレコードに絞っています。
これを合わせると、20歳以上の男性か、身長が170cm以上〜180cm未満のどちらかに合致するレコードを対象としています。
並び替え
SELECT * FROM 従業員表 ORDER BY 氏名 ASC
ORDER BY句
は続けて書かれるカラム名を基準にASC(昇順)、またはDESC(降順)に並び替えをしてくれます。
集計関数
集計合計とは指定したレコードの値の合計値、最大・最小値、平均、件数などを集計してくれます。
レコードを取得してわざわざforeach()でループを回さずに済みますね!
合計値
SELECT * SUM(案件獲得数) FROM 成績表 WHERE 活動年度 = '2022'
これはまず条件式から適用し、活動年度が2022年のレコードのみに絞っています。
そしてSUM(案件獲得数)
は、絞られたレコードから、案件獲得数の合計を呼び出します。
最大値
SELECT * MAX(レコード名) FROM テーブル名
合計値と同じ考え方で大丈夫です。
これはレコード名に対応した中での最大値を呼び出しています。
最小値
SELECT * MIN(レコード名) FROM テーブル名
こちらは逆に最小値を呼び出しています。
平均値
SELECT * AVG(レコード名) FROM テーブル名
こちらは平均値(Average)ですね。
SELECT * COUNT(レコード名) FROM テーブル名
最後は取得レコードの件数です。
グループ化
SELECT * FROM テーブル名 ORDER BY レコード名
ここまで来ると少しは感覚的に分かってきた頃ではないでしょうか。
ORDER BY句は続けて指定されたレコードごとにグルーピングしてくれます。
ORDER BY に対しての条件
SELECT * FROM 社員情報 ORDER BY 役職 HAVING NOT(役職 = '取締役')
グループ化する際にちょっとした条件を加えたいときも中にはあるでしょう。
そんなときはWHEREではなくHAVINGを使います。
ORDER BY句より前の条件式にはWHERE句、後の条件式にはHAVING句を使いましょう。
それではHAVING句の条件式を見てみると、NOT(役職 = '取締役')
となっています。
役職 = '取締役'
は分かりますね?
ではNOT(条件式)
のNOT()とは何でしょう?
NOTとは論理演算子の1つで、否定を意味します。
PHPで言えば!TRUE === FALSE
で伝わるでしょう。
つまりNOTとはその状態や意味を反転してしまうのです。
そうすると、NOT(役職 = '取締役')
とは役職が取締役ではないとなります。
そのため、このSQLは社員情報を役職ごとにグループ化する際に、取締役以外の役職を対象にするということを表しています。
複数を組み合わせた呼び出し
命令文の優先度
命令文には四則演算のような優先順位が存在します。
ここまで登場していない命令文もありますが、それらもひっくるめて優先順位をつけると下記のようになります。
FROM句 > JOIN句 > WHERE句 > GROUP BY句 > HAVING句 > SELECT句 > ORDER BY句 > LIMIT句
「あれ? SELECT句って一番最初じゃないの?」と思ったそこのあなた、鋭いですね!(謎の上から目線)
SELECT句ってなんでしたっけ?
SELECT句は最終的に呼び出すカラムを指定していますよね?
もし最初にカラムを指定されたら、SELECT句で宣言しなかったカラムは条件式などで使えなくなってしまいます。
そのため、SELECT句の優先順位は低いのです。
もちろん、ANDやORなどの論理演算子にも優先順位があります。
というか優先順位がないと全部頭から実行されてしまうため、式の逆説などもできないですしお寿司食べたい。
小休憩終了。
では本題の
組み合わせサンプル1
SELECT * COUNT(ゼッケン番号) FROM 選手表 WHERE 年齢 >= 16 AND 身長 >= 160 BETWEEN 身長 <= 200
組み合わせサンプル2
SELECT 氏名, 学年, 身長, 血液型 FROM 全校生徒表 WHERE 出欠 = ‘出席’ ORDER BY 学年 ASC GROUP BY 血液型 HAVING 誕生月 >= 4 AND 誕生月 <= 6
ビュー(最初からある程度条件を絞っておく)
CREATE VIEW 男子生徒 AS SELECT * FROM 全校生徒表 WHERE 性別 = ‘男子’
SELECT 生徒番号, 学年, 氏名 FROM 男子生徒 WHERE NOT(血液型 = ‘AB’)
コメント