技術情報

technology

【楽しく学ぶSQL入門】第14章:システム開発現場で差がつくSQL応用構文とインデックスの仕組み

システム開発において、基本となるデータ操作を習得した後に重要となるのが、より実戦的で高度なクエリ構文やパフォーマンスの最適化。効率的なコーディングと検索速度の向上を両立させることは、大規模なデータを扱う上での必須要件です。本章では、覚えておくと表現の幅が劇的に広がる応用テクニックについて詳しく見ていきましょう。 システム開発現場で差がつくSQL応用構文 EXISTS構文 複数のSELECT文を組み合わせるアプローチとして「副問い合わせ(サブクエリ)」や「テーブル結合(JOIN)」が挙げられる。しかし、特定のデータが存在するかどうか判定する場合、EXISTS句を使うことで、よりシンプルかつ高速にSQLを記述できる局面があります。 コピー SELECT 列名 FROM テーブル名 WHERE EXISTS ( 入れ子にするSELECT文 ); EXISTSは、主にWHERE句の中でデータの存在チェックを行う条件式として使用されます。条件に合致するレコードが「1件でも見つかった時点で判定を終了する」という性質があるため、データ量が多い場合に処理を大幅に効率化できるのが特徴。 具体的な動きをシミュレーションしてみましょう。例えば、以下のような「userテーブル」と「jobテーブル」が定義されているとします。それぞれのidは互いに対応関係を持っています。(例.id = 1の山田さんは営業職) 【userテーブル】 id name 1 山田 2 佐藤 3 小西 4 吉村 5 田中 【jobテーブル】 id job_name 1 営業 2 営業 3 技術 4 技術 5 事務 上記の状態から、EXISTSを用いて職種が「営業」であるユーザーのid and nameを抽出する場合、SQL文は以下のように組み立てます。 コピー SELECT id, name FROM user WHERE EXISTS ( SELECT * FROM job WHERE user.id = job.id AND job.job_name = ‘営業’ ); クエリの実行結果を確認しましょう。条件に合致したユーザーのみが出力されます。 id name 1 山田 2 佐藤 入れ子構造の内部にある 「user.id = job.id」 によって2つのテーブルの紐づきを制御し、かつ 「job.job_name = ‘営業’」 で絞り込み条件を表現する仕組みです。 なお、EXISTS句には存在しないことを条件とする否定形、すなわちNOT EXISTSも存在します。上記のSQLをNOT EXISTSに置き換えた場合、出力結果が反転してどのように変化するか、ぜひ考えてみてください。 参考サイト:MySQL 公式サイト(EXISTSサブクエリ) CASE WHEN構文 CASE WHEN構文を使用することで、SQLのデータ参照領域において、JavaプログラムのIF文やSWITCH文のような条件分岐をシミュレートすることが可能になります。2パターンの表記法を用途に応じて使い分けるのを意識すること。 Ⅰ.特定の値を直接評価して分岐する場合 特定の列の値をそのまま比較対象としてマッピングしていくシンプルな記述方法です。 コピー CASE 評価対象の列や式 WHEN 値1 THEN 値1の時に返す値 [WHEN 値2 THEN 値2の時に返す値] [ELSE デフォルト値] END 例として、収支テーブルの全データから日付、費目、および独自の「固定変動チェック」列を生成して取得してみましょう。費目が「定期代」であれば『固定費』、費目が「交通費」「飲食費」「娯楽費」なら『変動費』、それ以外の費目はすべて『不明』と明示して出力を試みます。 コピー SELECT income_and_expenditure_date, expense, CASE expense WHEN ‘定期代’ THEN ‘固定費’ WHEN ‘交通費’ THEN ‘変動費’ WHEN ‘飲食費’ THEN ‘変動費’ WHEN ‘娯楽費’ THEN ‘変動費’ ELSE ‘不明’ END AS 固定変動チェック FROM income_and_expenditure; Ⅱ.複雑な比較条件で判定・分岐する場合 WHENの直後に個別の不等号判定や論理式を記述できる、極めて汎用性の高いアプローチです。 コピー CASE WHEN 条件1 THEN 条件1の時に返す値 [WHEN 条件2 THEN 条件2の時に返す値] [ELSE デフォルト値] END 例として、出費額の多寡に応じたラベル判定(出費が30,000円ちょうどなら『定期代』、1,000円以下なら『小出費』、3,000円以下なら『中出費』、値が未入力(NULL)の場合は『出費ではない』、それ以外は一律『大出費』とする)を行うSQLを組み立てます。 コピー SELECT income_and_expenditure_date, expenditure, CASE WHEN expenditure = 30000 THEN ‘定期代’ WHEN expenditure

【楽しく学ぶSQL入門】第13章:正規化

システム開発において、効率的で欠陥のないデータベースを設計するためのアプローチとして、データの正規化があります。この概念を理解するのは少々難易度が高く、SQLをかじった程度では全体像を掴みにくいと感じるかもしれません。しかし、システム開発の設計フェーズにおける重要度は極めて高く、おさえておきたいポイントとなっているため、本章で紹介していきます。 正規化 データの正規化とは、データの管理を容易にするために、データの重複をなくす方法のこと。データを多様な目的で用いるのに有効であり、データベースの構築の基本となる技法です。ここでは、正規化されていないファイルを、第1正規化、第2正規化、第3正規化していく手順を見ていきましょう。 非正規型 以下のように、「1枚の伝票の中に最大3つの商品を同時に連記(並べて記載)できる」という業務運用ルールに則った売上伝票を想定してみましょう。 売 上 伝 票 売上年月日 2026年06月01日 得意先CD T01 得意先名 大阪商店 連記枠 商品CD 商品名 区分CD 区分名 数量 単価 商品① S01 リンゴ K01 果物 10 150 商品② S02 ミカン K01 果物 5 100 商品③ – (未記入) – – – – このように、データがバラバラに紙の伝票に書かれている状態です。これをそのまま1行のレコード(ファイル)としてデータベースに格納しようとすると、以下の表のようになってしまいます。 年月日 得意先CD 得意先名 商品CD1 商品名1 区分CD1 区分名1 数量1 単価1 商品CD2 商品名2 区分CD2 区分名2 数量2 単価2 商品CD3 商品名3 区分CD3 区分名3 数量3 単価3 2026-06-01 T01 大阪商店 S01 リンゴ K01 果物 10 150 S02 ミカン K01 果物 5 100 (空白) – – – – – 2026-06-02 T02 東京物産 S03 ブドウ K01 果物 2 300 (空白) – – – – – (空白) – – – – – 上の伝票のように「3つ目の商品が未記入」のとき、データベース上では右側に無駄な空白(NULL値)がずらりと並んでしまい、領域の無駄遣いが発生。これがシステム開発現場で非正規型が嫌われる理由です。 次項から、この無駄(商品2、商品3の横並び繰り返し)を美しく取り除く正規化の手順を説明していきます。 第1正規化 第1正規化とは、データ構造内の「繰り返し部分」を独立した複数のレコードへ展開し、繰り返しを排除する操作のこと。この処理を適用した結果のファイル構造を第1正規形と言います。非正規型にあった無駄な空白が解消されるのが最大の特徴です。 例えば、展開を行う対象ファイルが以下のような構成要素で成り立っているケースを想定してみましょう。各因果関係を正しく把握しておくことが設計上の前提となります。 対象ファイル名 内包されるデータ項目 売上ファイル1 年月日 + 得意先コード + 得意先名 + 商品コード + 商品名 + 商品区分コード + 商品区分名 + 数量 + 単価 このデータ構成において、「年月日」「得意先コード」「商品コード」の3つの要素すべてがバシッと定まると、テーブル内にある特定の1行(レコード)を一意に識別可能。このような役割を持つ項目群をデータベースの世界では主キーと定義します。 ここで重要となるのが、ある項目が定まると他の項目も必然的に導き出されるという「項目間の依存関係」であり、これを関数従属と呼びます。正規化を進める上での鍵。 例えば、「数量」は主キーである3つの項目すべてが揃って初めて確定しますが、このように主キー全体に依存する状態を完全関数従属と言います。一方で、「得意先コードが決まれば得意先名がわかる」という関係のように、複合主キーの一部だけに依存している状態を部分関数従属と呼びます。また、「商品コード」がわかれば「商品区分コード」がわかり、それにより「商品区分名」までわかる、というような間接的な依存関係が、推移関数従属になります。 年月日 得意先CD 得意先名 商品CD 商品名 区分CD 区分名 数量 単価 2026-06-01 T01 大阪商店 S01 リンゴ K01 果物 10 150 2026-06-01 T01 大阪商店 S02 ミカン K01 果物 5 100 2026-06-02 T02 東京物産 S03 ブドウ K01 果物 2 300 参考サイト:MySQL 公式サイト(主キーの最適化) 第2正規化 第2正規化とは、主キーの一部に対して従属している項目(部分関数従属)を別テーブルへと切り離す操作のことです。その結果として出来上がる構造を第2正規形と呼びます。システム開発現場では、この段階でデータの重複が大幅に削減されるため、設計の美しさを左右する重要な局面です。主キーである「年月日」「得意先コード」「商品コード」の3つに対し、各項目は以下のような連動関係を持っています。 年月日:単体で決まる項目は存在しない。 得意先コード:これが定まると「得意先名」が自動的に決まる(部分関数従属)。 商品コード:これが定まると「商品名」「商品区分コード」「商品区分名」「単価」が決まる(部分関数従属)。※単価は全社一律と想定 数量:3つの主キー(年月日・得意先コード・商品コード)がすべて揃って初めて確定する(完全関数従属)。 この従属関係を整理し、無駄のない形へ切り分けるために、元の巨大なファイルを以下の「3つの構成」へと分離・新設します。構造をイメージすることが理解への近道です。 【売上ファイル】 年月日 得意先CD 商品CD 数量 2026-06-01 T01 S01 10 2026-06-01 T01 S02 5 2026-06-02 T02 S03 2 【得意先マスタ】 得意先CD 得意先名 T01 大阪商店 T02 東京物産 【商品マスタ(第2正規形段階)】 商品CD 商品名 区分CD 区分名 単価 S01 リンゴ K01 果物 150 S02 ミカン K01 果物 100 S03 ブドウ K01 果物 300 参考サイト:MySQL 公式サイト(InnoDB テーブルの設計) 第3正規化 第3正規化とは、主キー以外の項目(主キーではない一般の列)に対して関数従属している非キー項目(推移関数従属)を、さらに別マスタへと分離独立させる最終プロセスのこと。この結果として導き出される完成形を第3正規形と言います。システム開発の設計フェーズにて、不可欠となる重要な仕上げ作業です。 前段階のファイルを精査すると、以下の特性が見えてきます。 「得意先マスタ」の得意先名は、主キーである得意先コードに直結しているため、これ以上の分離は不要。 「売上ファイル」の数量も、複合主キー全体に完全関数従属しているため、これ以上の分解は不可能。 したがって、今回の最適化の標的となるのは「商品マスタ」のみになる。 第2正規形段階の「商品マスタ(商品コード + 商品名 + 商品区分コード + 商品区分名 + 単価)」において、主キー以外の項目である「商品区分コード」が定まると、連動して「商品区分名」が一意に決定する関係(推移関数従属)が存在。そのため、この部分を独立したファイルとして切り離します。 分離・新設ファイル名 構成される項目(太字は主キー) 商品区分マスタ 商品区分コード + 商品区分名 商品マスタ(確定) 商品コード + 商品名 + 商品区分コード + 単価 すなわち、最終的にデータベース上に構築される第3正規形のファイル群は、以下の「4つのファイル」へと美しく集約されます。データ構造の重複が完全に排除された状態。 【売上ファイル(確定)】 年月日 得意先CD 商品CD 数量 2026-06-01 T01 S01 10 2026-06-01 T01 S02 5 2026-06-02 T02 S03 2 【得意先マスタ(確定)】 得意先CD 得意先名 T01 大阪商店 T02 東京物産 【商品マスタ(確定)】 商品CD 商品名 区分CD 単価 S01 リンゴ K01 150 S02 ミカン K01 100 S03 ブドウ K01 300 【商品区分マスタ(新設)】 商品区分CD 商品区分名 K01 果物 実は正規化には、第5正規化まで手法が存在します。しかし、本章では第3正規化までしか説明していません。第3正規化まで理解できていれば十分ですが、興味があるならぜひ調べてみてください。 参考サイト:MySQL 公式サイト(データベースの最適化) PICK UP あわせて読みたいSQL基礎知識 【楽しく学ぶSQL入門】第10章:トランザクション制御 【楽しく学ぶSQL入門】第11章:テーブル 【楽しく学ぶSQL入門】第12章:ビュー 【楽しく学ぶSQL入門】第14章:システム開発現場で差がつくSQL応用構文とインデックスの仕組み

【楽しく学ぶSQL入門】第12章:ビュー

システム開発において、複雑なデータ検索を効率化し、セキュリティや運用の利便性を高めるために多用される重要な仕組み、それがビュー。データベース設計の洗練度を左右する要素でもあります。本章では、ビューの基本的な概念から作成・削除の手順まで、その構造を詳しく見ていきましょう。 ビュー ビューとは、データベース内に実データを持たない「架空のテーブル」のこと。物理的なテーブルには実際のレコードが直接格納されますが、ビューは特定の検索結果を映し出す鏡のような役割を果たします。これを通すことで、データをより閲覧しやすく、あるいは管理しやすくコントロールできるのがメリット。ざっくり言うと、”長くて複雑な結合SQLを何度も書かなくて済むための仕組み”と言えます。 単一ビュー&複合ビュー ビューは、作成完了後も通常のテーブルとほとんど同じ感覚(SELECT文だけでなく一部のDML文の発行など)で扱うことが可能です。しかし、定義の仕方によって次の2種類のビューに分類され、データの操作に関する性質が少々変わってきます。 単一ビュー 一つのテーブルだけを元にして作成される。 SQL関数を定義内に含まない。 GROUP BY句などのグループ化処理を含まない。 ビューに対して、直接データの追加(INSERT)、更新(UPDATE)、削除(DELETE)が可能である。 複合ビュー 複数のテーブルを結合(JOIN)して作成される。 SQL関数を定義内に含む。 GROUP BY句などのグループ化処理を含む。 ビューに対してデータの追加、更新、削除を行うことは不可能である。 参考サイト:MySQL 公式サイト(ビュー) ビューの作成 新しくビューを定義・構築する際は、CREATE VIEW文を発行します。基本的な定義方法は「既存表からのテーブル作成(AS SELECT)」と全く同じスタイル。非常にシンプルな形です。 コピー CREATE [OR REPLACE] VIEW ビュー名 AS SELECT文 [WITH READ ONLY]; ただし、通常のテーブル作成と大きく異なる点が1点あります。ビューには、定義変更を行うためのALTER文が存在しません。そのため、定義を修正したいときには代わりにOR REPLACEオプションを付与し、既存の定義ごと上書き置換を行う必要があります。 このオプションは、すでに同一名称のビューがデータベース内に存在している場合のみに効果を発揮します。既存のものがない新規作成時でもエラーにはならないため、常に記述していても問題はありません。システム開発現場における作業効率を高めるためにも、常に記述することを推奨します。 WITH READ ONLYオプションは、そのビューを強制的に「読み取り専用(データ変更を一切認めない)」に制限したい場合に付加するパラメータ。なお、先述した「複合ビュー」として作成したビューは、データベースのシステム特性として自動的に読み取り専用属性となるため、その際は明示的にこのオプションを付加する必要はありません。 参考サイト:MySQL 公式サイト(CREATE VIEW 構文) ビューの削除 不要になった架空のテーブル構造をデータベースから消去する際は、DROP VIEW文を使用します。 コピー DROP VIEW ビュー名; ビューを削除しても、そのビューの元になっているベース of 物理テーブルや、そこに格納されている実際のデータレコード自体が消去されることはありません。あくまで架空の窓口を削除するのみ。 参考サイト:MySQL 公式サイト(DROP VIEW 構文) PICK UP あわせて読みたいSQL基礎知識 【楽しく学ぶSQL入門】第9章:データの挿入・更新・削除 【楽しく学ぶSQL入門】第10章:トランザクション制御 【楽しく学ぶSQL入門】第11章:テーブル 【楽しく学ぶSQL入門】第13章:正規化 【楽しく学ぶSQL入門】第14章:システム開発現場で差がつくSQL応用構文とインデックスの仕組み

【楽しく学ぶSQL入門】第11章:テーブル

システム開発において、データを効率よく安全に管理するためには、適切な構造を持ったテーブルの設計が不可欠です。本章では、テーブルの作成から変更、削除に至るDDL(データ定義言語)の基本構造について見ていきましょう。 テーブル データベース内に新しい実体として定義される表のまとまり、それがテーブルです。用途に応じて列を組み合わせ、システム開発現場に必要なデータ構造を定義していきます。 テーブルの作成 データベースに対して新しいテーブルを定義・構築する際に使用するのが、CREATE TABLE文。列名や対応するデータ型、格納時のルールとなる制約を1つずつ組み上げていくのが基本手順です。 コピー CREATE TABLE 表名 ( 列名 データ型 [制約 DEFAULT値など], 列名 データ型 [制約 DEFAULT値など], … ); 列に対してDEFAULTオプションを付与することによって、データ挿入時に値が省略された場合、あらかじめ決めたデフォルトの値を自動的に指定することができます。システム開発現場における入力漏れを防ぐ実用的な設定です DEFAULTオプションの割り当てには、固定の文字列や数値といったリテラルのほか、式やSYSDATE等のSQL関数をセットすることもできます。 コピー CREATE TABLE income_and_expenditure ( id INT NOT NULL AUTO_INCREMENT, expense VARCHAR(13), income_and_expenditure_date DATE, income INT DEFAULT 0, expenditure INT DEFAULT 0, comment VARCHAR(100), PRIMARY KEY (id) ); データ型直後にあるカッコ内の数値は、格納できる許容量(バイト数や桁数)を示します。また、テーブルの列にはデータ整合性を守るための制約指定することも可能。NOT NULL制約は上記の通り列ごとに定義を行い、指定なしの列にはNULLをセットすることが許容される仕組みです。 PRIMARY KEY(主キー)制約は、指定した列の値によって行が一意に限定され(UNIQUE KEY制約)、なおかつNULLの格納を一切認めない(NOT NULL制約)という2つの重要な役割を合わせ持つ強力な制約です。 最後に注意点として、同じデータベースユーザーが同一名のテーブルを重複して作成することはシステム仕様上認められません。実行を試みるとエラーが発生します。 ※KEY(制約)の種類 テーブル内の列には、データの品質を担保するために列ごとの役割(KEY、または制約)を与えるのが一般的。以下が主要な制約の名称と特性になります。 UNIQUE KEY:指定した列内で、他の行と同じ値が重複して混入することを禁止。 NOT NULL KEY:指定した列に対し、値が未入力の状態(NULL値)となることを禁止。 PRIMARY KEY:UNIQUE特性とNOT NULL特性を同時に兼ね備えた、行を識別するための必須制約。 FOREIGN KEY:他のテーブルの列(参照先)を参照し、そこに存在しない無効な値の登録を禁止。ただし、参照先となる相手側の列は、あらかじめUNIQUEかPRIMARY KEYのいずれかに設定されていることが必須条件。 参考サイト:MySQL 公式サイト(CREATE TABLE 構文) テーブルの削除 不要になったテーブルを構造ごとデータベース内から完全に消去する際には、DROP TABLE文を実行します。 コピー DROP TABLE 表名; テーブル削除を行う状況において、エラーを誘発する明確なパターンが1つ存在します。それがFOREIGN KEYによる参照整合性制約。他のテーブルから参照されている状態で親の表を消すことはシステム上不可。このエラーを回避するためには、関連する制約をあらかじめ解除するか、依存している子テーブルを先に処理する手順の構築が不可欠です。 参考サイト:MySQL 公式サイト(DROP TABLE 構文) テーブル名の変更 構築済みのテーブル名称を別の名前に変更したい場合は、ALTER TABLE文にRENAME句を組み合わせて発行します。 コピー ALTER TABLE 元の表名 RENAME 新しい表名; テーブルの変更(列の追加) 既存のテーブル構造に新たなデータ項目を付け足したいときは、ALTER TABLE文に対してADDコマンドを指定します。 コピー ALTER TABLE 表名 ADD 列名 データ型 [制約 DEFAULT値など], …; 列を追加する際、DEFAULTオプションをあえて指定しなかった場合、既存レコードの追加列にはすべてNULLが初期値としてセットされます。この新規追加された列は、必ず既存テーブルの定義の最後尾に配置される仕組みです。 テーブルの変更(列の変更) 定義済みの列に対して名称や属性を変更する場合は、目的によってCHANGE句、またはMODIFY句を使い分ける必要があります。 ・列名そのものをリネームしたいとき: コピー ALTER TABLE 表名 CHANGE 元の列名 新しい列名 データ型 [制約 DEFAULT値など]; ・列名はそのままで、データ型や制約の特性をアップデートしたいとき: コピー ALTER TABLE 表名 MODIFY 列名 データ型 [制約 DEFAULT値など], …; 既存テーブルに対して列の変更をかける際には、データベースのデータ破損を防ぐための厳格な制限事項が存在します。事前に内容を精査しておかなければ実行失敗の原因となります。仕様を網羅しておきましょう。 列の最大サイズ(許容バイト数)を拡張・拡大する処理は、データ状態に関わらず常に実行可能。 列の許容サイズを縮小・削減したい場合は、対象テーブルのレコード数が完全にゼロであるか、あるいは変更対象列のデータがすべてNULLの状態で埋まっていることが前提条件。 新たなNOT NULL制約を途中から追加する際は、テーブルにデータが一切格納されていないか、既存の該当列データ内にNULL値が一箇所も残存していない状態が必須。 MODIFY句の単体の指定によって直接変更・操作が可能な制約属性は、システム特性上NOT NULL制約のみ。 列のDEFAULT値を途中で変更した場合、その変更内容が有効化されるのは「今後のデータ挿入時(INSERT)」から。既存データへの遡及適用はなし。 参考サイト:MySQL 公式サイト(ALTER TABLE 構文) テーブルの変更(列の削除) テーブル内から不要な列項目そのものを除去したい場合は、ALTER TABLE文にDROP句を指定します。 コピー ALTER TABLE 表名 DROP 列名; データ構造を消し去る強力なコマンドであるため、列の削除機能にもいくつかの明確な制約が存在します。不用意な実行はトラブルの元となるため、注意してください。 1度のSQL文発行手続きにおいて、個別に削除指定ができるのは1列のみ。 テーブル構造を維持する仕様上、内部に存在する「最後の1列」を削除してゼロにすることは不可。 1度削除コマンドを完遂した構造およびデータは、後方からの復元(ロールバック)不可。(DDLの暗黙のコミット) 削除対象の列にデータが格納されていても、削除は可能。 制約の変更(NOT NULL 制約は除く) すでに設定されている制約(主キーや外部キーなど)を後から変更する場合、直接上書きするコマンドは存在しません。一度既存の制約を明示的に削除し、その後に新定義を追加する二段階の手順を踏む必要があります。さらに、テーブル内にレコードが存在する場合には、格納済みの実データが新しい制約ルールをクリアしていないとエラーが返るため、事前の精査が肝心です。 制約の追加や削除を実施する場合も、列操作と同様にADDやDROPのコマンドをALTER TABLEに組み合わせて発行します。 コピー ALTER TABLE 表名 ADD 列名 型 制約; ALTER TABLE 表名 DROP 列名 型 制約; 既存テーブルからのテーブル作成 テーブルを作成するアプローチには、ゼロから真っさらに定義する方法だけでなく、既存のテーブルに格納されているデータを抽出してそのまま新しい表として複製・新設する便利な手法が存在します。 ① 例)既存データの中から、支出があるデータに合致したレコードをベースに、別名で新規テーブルを構築します。 コピー CREATE TABLE test AS SELECT * FROM income_and_expenditure WHERE expenditure > 0; この記述内に組み込むSELECT文には、通常のデータ検索で使用するクエリ構文をそのまま流用できます。もちろん、複数のテーブルを結合して抽出した複雑な結果から新しい表を作成することも可能。 (参考)作成の副次的な効果として、選択した各列に対して新しい別名を割り当てて定義することも可能です。また元のテーブルに入っていた実データの値はそのまま新テーブルへ反映されます。ただし、構造上のルールである「制約」に関しては、唯一NOT NULL制約のみが引き継がれる仕様です。主キー(PRIMARY KEY)や外部キーなどの他の各種制約については、表の作成が完了した後に、改めて個別に手動で追加定義を施す必要がある点に留意してください。 参考サイト:MySQL 公式サイト(CREATE TABLE … SELECT 構文) PICK UP あわせて読みたいSQL基礎知識 【楽しく学ぶSQL入門】第8章:結合 【楽しく学ぶSQL入門】第9章:データの挿入・更新・削除 【楽しく学ぶSQL入門】第10章:トランザクション制御 【楽しく学ぶSQL入門】第12章:ビュー 【楽しく学ぶSQL入門】第13章:正規化 【楽しく学ぶSQL入門】第14章:システム開発現場で差がつくSQL応用構文とインデックスの仕組み

【楽しく学ぶSQL入門】第10章:トランザクション制御

システム開発において、データベースの整合性を保つための強力な仕組みをトランザクション制御と呼びます。この概念を理解するのは少々難易度が高く、SQLをかじった程度では全体像を掴みにくいと感じるかもしれません。しかし、システム開発現場における優先度は極めて高く、特に「排他制御」の観点から外せない要素。そのため、本章でしっかりおさえておきましょう。 トランザクション制御 トランザクションとは、データの確定から次のデータ確定までの期間を指す言葉。データが確定している状態とは、一言でいえば「誰が見ても同じ状態」であることです。 DML(データ操作)文を発行すると、テーブル内のデータは書き換わります。しかし、実はこの時点ではまだデータは確定していません。変更を行った本人にしか見えない状態。では、他のメンバーにも見えるように変更を反映させたいときはどうするか。ここでDCL(データ制御)文の出番というわけです。 COMMIT:更新の確定 ROLLBACK:更新の取消 SAVEPOINT:セーブポイントの設定 このCOMMITを使用すると、自分の行った変更が他の人も閲覧できるように確定されます。逆にROLLBACKを実行すると、周囲の目に触れる前に自分の変更を取り消すことができます。そしてSAVEPOINTは、ロールバックを実行して元の状態に戻す位置を指定するために利用します。 トランザクションの動きはシンプル。要するに変更を行った際には、最後に必ずCOMMITを実行しなければならない、ということです。 一つのトランザクションが終了すれば、次のトランザクションが即座にスタートします。その時点で確定されているデータは、すぐに閲覧や操作が可能です。これによってデータの整合性が保たれ、誰がテーブル内を変更していても同じ最新の状態を閲覧できる。この仕組みを「読み取り一貫性」と呼びます。 ここで具体的な処理の流れを確認しましょう。以下にトランザクションを実行するSQLの一例を示します。データが確定(COMMIT)してから、次の確定を迎えるまでの処理範囲を視覚的に整理することが理解への近道です。処理の途中でエラーが起きた状況を想定し、セーブポイントを活用した制御の流れを追っていきます。 ここでは、システム開発現場でよくある連続的なデータ操作のシミュレーションとして、従業員データを更新する手順を例に挙げました。手順のナンバリングに沿って確認してください。

【楽しく学ぶSQL入門】第9章:データの挿入・更新・削除

システム開発において、データベースのデータを操作する技術は根幹を成す要素です。データを新しく追加する、既存の状態を更新する、不要なレコードを削除するといった処理がそれに当たります。本章では、それらのデータ操作を司るSQLの基本構造について見ていきましょう。 INSERT文…データを登録する テーブルに対して新しいレコードを書き加える際に使用するのがINSERT文です。データを新しく登録するための最も基本的な仕組みとなります。 INSERT INTO 表名 [ ( 列名 , 列名 , ・・・) ] VALUES ( 値 , 値 , ・・・) ; [列名]を指定した順に[値]を指定してください。もちろん双方の指定する数は同じでないといけません。数がズレるとエラーになります。整合性がポイント。 また、[列名]の記述自体を省略することも可能です。しかしその時は、そのテーブル内に存在する全ての列に対して[値]を順番通りに指定しなければいけません。複数の[列名]や[値]を指定する時は、区切りのカンマ(,)も必須です。配置に気をつけましょう。 ① 例)「田中太郎」を登録する。 コピー INSERT INTO employee (employee_id, group_id, name1, name2, sex_id, age) VALUES (31, 1, ‘田中’, ‘太郎’, 1, 30); 参考サイト:MySQL 公式サイト(INSERT 構文) UPDATE文…データを更新する 既にテーブル内に存在しているデータを、新しい値へ書き換える処理を行うのがUPDATE文です。 UPDATE 表名 SET 列名 = 値 [ , 列名 = 値, 列名 = 値, ・・・・・・ ] [ WHERE 条件式 ]; SET句に対して、変更処理を行いたい列とその値を指定します。複数の列を一括で指定する場合は、カンマで区切るのが鉄則です。WHERE句では、値を変更したい行の抽出条件を指定してください。この指定の手順は、データを検索するSELECT文と同様。それゆえ指定条件に該当する複数の行が同時に変更されてしまうケースもあるので、上手く条件を指定するようにしましょう。 なお、WHERE句は省略することも可能ですが、その場合は特定の行ではなくテーブル内の全行が変更対象となってしまいます。大規模なデータ書き換えを招く恐れがあるため注意し、慎重に運用してください。 ② 例)特定の社員データを書き換える。 コピー UPDATE employee SET group_id = 2, age = 31 WHERE employee_id = 31; (参考)UPDATE文は、1行も更新ができなかった場合でもSQL自体はエラーを返しません。しかし、実際のシステム開発現場でUPDATE文を発行するときは、必ず何らかのデータを書き換えたいはず。そのため、システム開発現場でUPDATEを組み込む際は、1行も更新されなかった場合を明示的にエラーとしてハンドリングする実装が求められることもあります。 参考サイト:MySQL 公式サイト(UPDATE 構文) DELETE文…データを削除する 不要になってしまった行データを、テーブル内から完全に消去するためのSQL文がDELETE文です。 DELETE FROM 表名 [ WHERE 条件式 ]; WHERE句で指定した条件式に一致する行を、すべて削除する仕様となっています。このWHERE句は、省略することが可能です。ただしその場合は絞り込みが行われないため、指定テーブル内のすべての行が一度に削除されてしまいます。実行には細心の注意を払ってください。また、利用するデータベース製品のシステム特性によっては、WHERE句と一緒にFROM句すらも省略して実行できるものもあります。 ③ 例)特定の社員データをテーブルから削除する。 コピー DELETE FROM employee WHERE employee_id = 31; 参考サイト:MySQL 公式サイト(DELETE 構文) SQLの分類 SQLコマンドは、その目的や扱う対象によって、大きく次の3つの言語体系に分類することが可能です。整理して把握しておきましょう。 SQLの3大分類とコマンド例 分類 概要 SQL文 DML データ操作 SELECT / INSERT / UPDATE / DELETE DDL データ定義 CREATE DATABASE / DROP DATABASE / CREATE USER / DROP USER / CREATE TABLE / DROP TABLE など… DCL データ制御 START TRANSACTION / COMMIT / ROLLBACK / GRANT / REVOKE PICK UP あわせて読みたいSQL基礎知識 【楽しく学ぶSQL入門】第6章:グループ化と集計処理 【楽しく学ぶSQL入門】第7章:副問い合わせ 【楽しく学ぶSQL入門】第8章:結合 【楽しく学ぶSQL入門】第10章:トランザクション制御 【楽しく学ぶSQL入門】第11章:テーブル 【楽しく学ぶSQL入門】第12章:ビュー

【楽しく学ぶSQL入門】第8章:結合

システム開発の現場では、単一のテーブルから値を取得することはほとんどなく、複数のテーブルに分散したデータを組み合わせて活用するケースが圧倒的に多いです。このように、複数の表を一つに繋ぎ合わせる操作を結合と言います。実際のシステム開発でのデータベース設計に深く関わる重要な仕組みなので、基本から丁寧に確認していきましょう。 結合の基本構文 SELECT 選択列リスト FROM テーブルA INNER JOIN テーブルB ON 両テーブルの結合条件 ※SELECT句の選択列リストには両テーブルの列を指定可能。 ① 例)社員テーブルとグループテーブルを結合し、社員名と所属グループ名を取得する。 コピー SELECT ep.name1, ep.name2, cg.name FROM employee AS ep INNER JOIN company_group AS cg ON ep.group_id = cg.group_id ; name1 name2 name 山田 次郎 システム開発部 佐藤 花子 人事総務部 INNER JOINというキーワードを用いずにテーブルを結合する方法もあります。古いシステムなどで見られる書き方。 SELECT 選択列リスト FROM テーブルA,テーブルB WHERE 両テーブルの結合条件 ② 例)FROM句に複数のテーブルを並べて結合し、社員名と所属グループ名を取得する。 コピー SELECT ep.name1, ep.name2, cg.name FROM employee AS ep, company_group AS cg WHERE ep.group_id = cg.group_id ; ※使用する場合は、以下の点に注意 ・全てのテーブルをFROM句に並列で記述するため、主となるテーブルがどれなのかがわかりにくくなる。 ・WHERE句には絞り込み条件も記述するため、結合条件がどれなのかわかりにくくなる。 可読性を損なう恐れがあるため、基本的にはINNER JOINを使うことが推奨されています。 参考サイト:MySQL 公式サイト(JOIN 構文) 外部結合 INNER JOINを使った通常の結合方法だと、指定した他方のテーブルの値がNULLの場合は、列が検索されて来ないという特徴があります。そこで登場するのが外部結合。他方の値がNULL又は存在しない場合でも検索することが可能になります。データの欠損を防ぎたい場面で非常に有効な手法と言えます。 まずは、通常のINNER JOINで特定のID以降の社員データを取得してみましょう。グループに未所属の社員がいる場合、その行は出力から除外されてしまいます。 ③ 例)INNER JOINを用いてIDが30以上の社員の結合データを取得する。 コピー SELECT ep.employee_id, ep.group_id, ep.name1, ep.name2, cg.name FROM employee ep INNER JOIN company_group cg ON ep.group_id = cg.group_id WHERE employee_id >= 30; employee_id group_id name1 name2 name 30 1 山田 次郎 システム開発部 これに対し、左側のテーブル(FROM句に書いた表)のデータを主軸とし、右側の値がNULLであっても強制的に全行を抽出するのが 「左外部結合」です。記述スタイルを確認しましょう。 SELECT 選択列リスト FROM 左表の名前 LEFT OUTER JOIN 右表の名前 ON 結合条件 ④ 例)LEFT OUTER JOINを用いてグループ未所属の社員も含めてデータを取得する。 コピー SELECT ep.employee_id, ep.group_id, ep.name1, ep.name2, cg.name FROM employee ep LEFT OUTER JOIN company_group cg ON ep.group_id = cg.group_id WHERE employee_id >= 30; employee_id group_id name1 name2 name 30 1 山田 次郎 システム開発部 31 NULL 鈴木 一郎 (NULL) ※大阪支社所属(未割当) 今度は、右側のテーブル(JOINの後ろに書いた表)を主軸としてデータを合流させる 「右外部結合」の構造です。 SELECT 選択列リスト FROM 左表の名前 RIGHT OUTER JOIN 右表の名前 ON 結合条件 ⑤ 例)RIGHT OUTER JOINを用いて対応する社員がいないグループも含めてデータを取得する。 コピー SELECT ep.employee_id, ep.group_id, ep.name1, ep.name2, cg.name FROM employee ep RIGHT OUTER JOIN company_group cg ON ep.group_id = cg.group_id ORDER BY employee_id; employee_id group_id name1 name2 name 30 1 山田 次郎 システム開発部 (NULL) (NULL) (NULL) (NULL) 新規プロジェクト準備室 最後に、左右のテーブルの双方に存在する未合致データをすべて含めて抽出する、 「完全外部結合」の仕様がこちら。 SELECT 選択列リスト FROM 左表の名前 FULL OUTER JOIN 右表の名前 ON 結合条件 ※MySQLでは直接FULL OUTER JOINは利用できない場合があります。そのためシステム開発現場で完全外部結合と同等の結果が欲しい場合は、LEFT JOINとRIGHT JOINの双方をUNION句で連結するなどの代替アプローチを採るのが一般的。 SELECT 選択列リスト FROM テーブルA, テーブルB WHERE テーブルAの結合条件列 = テーブルBの結合条件列(+) これで左外部結合になる。 自己結合(再帰結合) 結合は異なるテーブル間で行うことが一般的ですが、自分自身と結合されることも可能です。同一テーブル同士を結合することを自己結合や再帰結合です。社員データとその上司のデータを結びつけるような組織ツリーの階層表現などで多用される設計技法となっています。 非等価結合 結合の条件に等価記号を用いた結合条件を指定することがほとんどですが、= 以外の演算子を用いた条件式も記述できます。このような結合を非等価結合と呼びます。金額に応じた評価ランクをマスタから引っ張るなど、範囲にグラデーションを持たせてデータを紐解く際に極めて有効な選択肢です。 PICK UP あわせて読みたいSQL基礎知識 【楽しく学ぶSQL入門】第5章:単一行関数とデータ型 【楽しく学ぶSQL入門】第6章:グループ化と集計処理 【楽しく学ぶSQL入門】第7章:副問い合わせ 【楽しく学ぶSQL入門】第9章:データの挿入・更新・削除 【楽しく学ぶSQL入門】第10章:トランザクション制御 【楽しく学ぶSQL入門】第11章:テーブル

【楽しく学ぶSQL入門】第7章:副問い合わせ

システム開発の現場では、複雑な条件を満たすデータを抽出するために、複数のクエリを組み合わせたい場面によく遭遇します。SQL文の中にSELECT文をネストする、このようなSQL文のことを副問い合わせや副照会、サブクエリなどと呼びます。非常に便利な構文ですが、少しややこしくなるのできちんと理解しておきましょう。 参考サイト:MySQL 公式サイト(サブクエリ) 副問い合わせは検索結果の種類によって主に3パターンに分類されます。それぞれの特徴と具体的な記述スタイルを以下のようにまとめました。 単一行副問い合わせ 検索結果が、「1行1列の値」となる副問い合わせ。単一の値を記述するような場所であれば、基本的にどこでも記述することが可能。 特定の数値を直接書き込む代わりに、別のクエリの計算結果をそのまま代入するイメージです。実際の記述例を確認してみましょう。 ① 例)収支テーブルからID = 1と同じ費目の出費を取得する。 コピー SELECT expense, expenditure FROM income_and_expenditure WHERE expense = (SELECT expense FROM income_and_expenditure WHERE id = 1); expense expenditure 飲食費 1000 飲食費 500 ② 例)収支テーブルから費目が飲食費の日付と出費額と飲食費合計を取得する。 コピー SELECT income_and_expenditure_date, expenditure, (SELECT SUM(expenditure) FROM income_and_expenditure WHERE expense = ‘飲食費’) AS ‘飲食費合計’ FROM income_and_expenditure WHERE expense = ‘飲食費’; date expenditure 飲食費合計 2026/05/11 1000 1500 2026/05/12 500 1500 複数列副問い合わせ 検索結果が、「複数の行から成る単一列の値」となる副問い合わせ。SQL文中で複数の値を列挙するような場所に、その代わりとして記述することが可能で、IN演算子を用いた条件式が代表的な事例です。 条件に合致する複数の候補リストを、内側のクエリが自動的に作成してくれます。 ③ 例)収支テーブルから5000円以上の出費があった費目の全ての収支情報を取得する。 コピー SELECT * FROM income_and_expenditure WHERE expense IN (SELECT DISTINCT expense FROM income_and_expenditure WHERE expenditure >= 5000); id expense expenditure remarks 1 交通費 5400 大阪出張移動費 2 交通費 800 近隣交通費 3 宿泊費 8500 ホテル宿泊代 表形式の副問い合わせ 検索結果が、「複数行と複数の列から成る表形式」となる副問い合わせ。通常のSQL文において表を記述することのできる場所、例えばSELECT文のFROM句などに記述します。 クエリによって一時的に作られた仮想のテーブルを、外側のSELECT文でさらに加工するような柔軟なデータ操作を実現できます。 ④ 例)費目が交通費と定期代の出費額の合計を取得する。 コピー SELECT SUM(SUB.expenditure) FROM (SELECT * FROM income_and_expenditure WHERE expense IN(‘交通費’, ‘定期代’)) AS SUB; SUM(SUB.expenditure) 15400 PICK UP あわせて読みたいSQL基礎知識 【楽しく学ぶSQL入門】第4章:検索結果の加工 【楽しく学ぶSQL入門】第5章:単一行関数とデータ型 【楽しく学ぶSQL入門】第6章:グループ化と集計処理 【楽しく学ぶSQL入門】第8章:結合 【楽しく学ぶSQL入門】第9章:データの挿入・更新・削除 【楽しく学ぶSQL入門】第10章:トランザクション制御

【楽しく学ぶSQL入門】第6章:グループ化と集計処理

システム開発の現場において、大量のデータから平均や合計といったグループごとの数値を算出するケースは日常茶飯事と言えます。本章で取り上げるのは、行のまとまりごとに情報を整理して計算するアプローチ。WHERE句による絞り込みとは一味違う、データ集約の手法を学んでいきましょう。まずは基本となる関数からスタートします。 集計関数(グループ関数) 複数の行をまとめて計算し、最終的に1つの結果を導き出す仕組みを集計関数と呼びます。記述できる場所は限定されており、主にSELECT文のSELECT句、ORDER BY句、あるいは後述するHAVING句のいずれか。ここでは、代表的な5つの集計関数について特徴を確認しておきましょう。 ・AVG関数:AVG( n ) ➔ nの平均値を返す。対象として指定できるのは数値のみ。 ・MAX関数:MAX( expr ) ➔ exprの最大値を出力。数値だけでなく文字列や日付型も指定可能で、文字列なら辞書順の死後、日付なら最も新しい日時が選ばれる仕組み。 ・MIN関数:MIN( expr ) ➔ exprの最小値を取得。数値、文字列、日付型に対応しており、文字列なら辞書順の先頭、日付なら最も古い日時を返す。 ・SUM関数:SUM( n ) ➔ nの合計値を算出。AVGと同様に数値型のみ受け付ける特性を持つ。 ・COUNT関数:COUNT( expr ) ➔ 条件に合致する行数をカウント。引数には特定の列名だけでなく、*(アスタリスク)をセットすることもできる。 COUNT関数に*(アスタリスク)をセットした場合は、単純にすべての行数をカウントします。対して特定の列名を指定したケースでは、その列の値がNULLである行を自動的に除外して集計する仕組み。この挙動の違いは、システム開発現場のデータ抽出において非常に大きな分かれ目となります。 ① 例)社員テーブルに何件のデータがあるか取得する。 コピー SELECT COUNT(*) FROM employee; COUNT(*) 19 ② 例)社員テーブルから電話番号を登録しているのは何件あるか取得する。 コピー SELECT COUNT(tel) FROM employee; COUNT(tel) 17 参考サイト:MySQL 公式サイト(Aggregate Functions) ここで、混同しがちな単一行関数との差異を整理しておきましょう。 単一行関数は各行に対して個別に計算を行うため、検索結果の行数自体が変わることはありません。しかし集計関数は、対象となったすべての行をひとまとめにして計算し、最終的に1つの答えを導き出します。結果として、結果表は必ず1行という形に集約されるのが大きな特徴です。これに伴い、複数行取得する列と集計関数を同時にSELECT文の選択列リストに入れることは原則できないため、コードを書く際は注意を払わなければなりません。 GROUP BY句とHAVING句 SQLには、指定した特定の基準に沿って検索結果をいくつかのチームやカテゴリに分けるグループ化という機能が備わっています。たとえば部署やクラスごとの平均点を算出したいとき、あるいは拠点(大阪本社、東京支社など)ごとの売上合計を弾き出したいときなどに重宝するシステム。グループ化を用いた集計処理は、以下のような構文スタイルに則って記述します。 コピー SELECT expense, SUM(expenditure), AVG(expenditure) FROM income_and_expenditure GROUP BY expense ; expense SUM(expenditure) AVG(expenditure) 飲食費 1500 750 交通費 800 800 ちなみに、GROUP BY句とHAVING句の並び順は順不可となっています。もし並び替えを行うORDER BY句を併用する場合は、必ず全体の末尾に配置しなければなりません。またGROUP BY句に指定するのは、SELECT句に用意した列の内、集計関数を使用していない列という鉄則もあります。SELECT句で集計関数を全く使用しないのであれば、GROUP BY句は不要です。 ③ 例)収支テーブルから費目別の出費合計と出費平均を取得する。 内部的なメカニズムに目を向けると、グループ集計の処理は3つのステップに沿って進行します。 1.元のテーブルに対して WHERE 句による通常検索処理が行われ、行が絞り込まれる。 2.GROUP BY 句で指定された列に同じ値を持つ行ごとに分類される。 3.各グループに対して集計関数の処理が行われた後、SELECT 句の選択列リストによって列が絞り込まれる。 この処理順序があるからこそ、大きな制約が生まれます。WHERE句が動いている段階では、システム内部でまだ合計や平均の計算が行われていません。したがって、集計関数はWHERE句に利用することはできないという絶対的なルールが確立されるわけです。もし集計処理がすべて完了した後の結果表に対して、さらに絞り込みの条件を課したい場合は、専用のHAVING句を書き足すことになります。 ④ 例)収支テーブルから費目別の出費合計が1円以上のデータを取得する。 コピー SELECT expense, SUM(expenditure) FROM income_and_expenditure GROUP BY expense HAVING SUM(expenditure) > 0 ; expense SUM(expenditure) 飲食費 1500 交通費 800 参考サイト:MySQL 公式サイト(GROUP BY Handling) 最後に、システム開発現場におけるちょっとしたコラムを紹介しておきます。実はHAVING句は、パフォーマンス面への影響から、実際のシステム開発プロジェクトで使用を禁じられるケースが少なくありません。一体なぜNGとされるのでしょうか。 本番環境のデータベースには、当然のように何百万件、あるいは何千万件もの膨大なデータが蓄積されています。しかしHAVING句は、一度全てのデータをグループ集計した後の結果表に対して、もう一度全件走査を行って絞り込みをかけるという内部仕様。安易に組み込むとサーバーのメモリやCPUに大きな負荷をかけてしまうため、システム開発現場で使用するにはインデックスの設計も含めた高い技術的注意が求められます。「それなら集計する前にWHERE句で行数を極限まで減らすべきだ」という開発思想から、一律で使用を禁止するルールを敷くチームが多いのが現状です。 PICK UP あわせて読みたいSQL基礎知識 【楽しく学ぶSQL入門】第3章:データの制限 【楽しく学ぶSQL入門】第4章:検索結果の加工 【楽しく学ぶSQL入門】第5章:単一行関数とデータ型 【楽しく学ぶSQL入門】第7章:副問い合わせ 【楽しく学ぶSQL入門】第8章:結合 【楽しく学ぶSQL入門】第9章:データの挿入・更新・削除

【楽しく学ぶSQL入門】第5章:単一行関数とデータ型

システム開発の現場では、データベースから取り出した生のデータをそのまま使うだけでなく、システム側で扱いやすい形に加工して出力するケースが多々あります。SQL文で利用できる関数には、1行ずつ処理を行う単一行関数と、複数の行をまとめる集計関数の2種類が存在します。今回は、実務での登場頻度が極めて高い単一行関数の使い方を見ていきましょう。合わせて、「データ型」の基本についても整理しておきます。 データ型 テーブルの列には、それぞれどのような種類の実体を格納するかという「型」があらかじめ決まっています。これがデータ型と呼ばれる概念。 データ種別 区分 代表的なデータ型名 数値 整数 INTEGER型 小数 DECIMAL型、REAL型 文字列 固定長 CHAR型 可変長 VARCHAR型 日付と時刻 – DATETIME型、DATE型、TIME型 利用可能なデータ型はDBMSによって異なります。ただし、ベースとなる数値型、文字列型、日付型の3つはどのシステムでも必ず用意されているのが特徴。実際の名称や細かな挙動は製品ごとに違いがあるため、注意が必要です。 ※文字列の「固定長」と「可変長」の違い 〇CHAR型は固定長の文字列データを扱うデータ型。たとえば「CHAR(10)」と指定された列では、内部であらかじめ10バイト分の記録領域が固定で確保されます。格納する文字列が10バイトに満たない場合、自動的に右側へ空白が詰められ、ぴったり10バイトに調整されて保存される仕組み。そのため、郵便番号や社員番号のように、入れるデータの桁数があらかじめ固定されている項目に向いています。 〇一方、VARCHAR型は可変長の文字列データを扱うデータ型。たとえば「VARCHAR(10)」と設定した列に3バイトや7バイトの文字が入力された場合、その文字数に合わせる形で領域が柔軟に変動するのが特徴。無駄なスペースが発生しないため、名前や住所など、桁数が変動する項目に最適です。 算術式 数値が格納されているデータに対しては、SELECT句の中で算術演算子を用いた四則演算を行うことができます。おなじみの算数と同じ計算方法をイメージしてください。 計算が評価される優先順位は、[乗算 * ]➔[除算 / ]➔[加算 + ]➔[減算 – ]の順番。一般的な数式と同じく、計算順序をコントロールしたい場合はカッコ( )で囲むことで優先順位を最も高く引き上げることが可能です。 ① 例)収支テーブルから0円以上の出費と、その金額に100円を加算した値を取得する。 コピー SELECT expenditure, expenditure + 100 FROM income_and_expenditure WHERE expenditure > 0 ; expenditure expenditure + 100 800 900 1500 1600 なお、SQLを用いると、テーブル de データを使わずに単純な計算式だけを実行することも可能。電卓のような使い方をイメージすると分かりやすいでしょう。 ② 例)SQLを使って数式の計算結果を出力する。 コピー SELECT (1+4)*2-6/3 FROM dual ; (1+4)*2-6/3 8 ここで登場した「DUAL表」は、こうしたちょっとした検証や計算を行うテスト環境のために用意された仮想のテーブル。ダミーテーブルと呼ばれることもあり、覚えておくと便利です。 また計算式に空データ(NULL)が含まれていると、どのような計算であっても結果は必ずNULLになってしまう点には注意してください。 ③ 例)NULLを含んだ除算を行う。 コピー SELECT 5/NULL FROM dual ; 5/NULL (NULL) 関数 SQLには、複雑なデータ加工や判定を自動化するための「関数」と呼ばれる命令セットが数多く用意されています。効率的な開発には欠かせません。 あらゆるシステムにおける共通のメカニズムとして、すべての関数は、「呼び出し時に指定した情報(引数)に対して、定められた処理を行い、結果(戻り値)に変換する」という挙動を取るのが基本。ただし、関数の種類や仕様はDBMSごとのバラつきが極めて大きい部分でもあります。以下で挙げる関数も、システムによっては動作しない場合があるため、あくまで基本モデルとして参考にしてください。 文字列に関する関数 ・CHAR_LENGTH( str ) :対象文字列(str)の「文字数」を返す。 ・LENGTH( str ) :対象文字列(str)の「バイト数」を返す。 ・TRIM( str ) :文字列の左右両端に存在する空白を除去した値を返す。 ・LTRIM( str ) :文字列の左側(前方)の空白を除去した値を返す。 ・RTRIM( str ) :文字列の右側(後方)の空白を除去した値を返す。 ・REPLACE( str, x, y ) :文字列(str)の中にある文字「x」を「y」へ置き換える。 ・SUBSTRING( str, m, n ) :文字列(str)の「m文字目」から「n文字分」をピンポイントで切り抜く。 ・CONCAT(str1, str2[, …]) :バラバラの文字列を1つに連結して出力する。 ④ 例)都道府県テーブルから都道府県名と、その文字数をカウントして取得する。 コピー SELECT name, CHAR_LENGTH(name) FROM pref ; name CHAR_LENGTH(name) 東京都 3 ● 大阪府 3 鹿児島県 4 参考サイト:MySQL 公式サイト(String Functions) 数値に関する関数 ・ROUND( m, n ) :数値(m)を任意の指定桁(n)で四捨五入する関数。 ・TRUNCATE( m, n ) :数値(m)を任意の指定桁(n)で切り捨て処理を行う。 ・POWER( m, n ) :数値(m)を「n乗」した累乗の計算結果を出力する。 ⑤ 例)収支テーブルの出費を百の位で四捨五入した値を取得する。 コピー SELECT expenditure, ROUND(expenditure, -3) FROM income_and_expenditure WHERE expenditure > 0; expenditure ROUND(expenditure, -3) 800 1000 1200 1000 桁数の指定(n)のルールは以下の通り。「1」:小数第2位を対象/「0」:小数第1位を対象/「-1」:1の位を対象/「-3」:百の位を対象(今回の例) 参考サイト:MySQL 公式サイト(Mathematical Functions) 日付に関する関数 ・CURRENT_DATE() :本日の日付(YYYY-MM-DD)を返す。 ・CURRENT_TIME() :現時点の時刻(HH:MM:SS)を出力する。 ・CURRENT_TIMESTAMP() :現在の日時(YYYY-MM-DD HH:MM:SS)をタイムスタンプ形式で取得する。 構造の見方:YYYYは西暦4桁、MMは月2桁、DDは日2桁。時刻のHHは時間2桁、MMは分2桁、SSは秒2桁を意味する。 ⑥ 例)現在のシステム日付を取得する。 コピー SELECT CURRENT_DATE() FROM dual; CURRENT_DATE() 2026-06-05 参考サイト:MySQL 公式サイト(Date and Time Functions) 変換に関する関数 ・CAST( a AS 変換する型 ) :対象データ(a)を、指定した別データ型へ変換する関数。 ・COALESCE( a, b, c[, …] ) :並べた引数の中から、**「最初に登場するNULLではない有効な値」**を選び出して返す。 ⑦ 例)社員テーブルから、もし電話番号(tel)が空(NULL)だった場合に代替文字を出力する。 コピー SELECT name1, name2, COALESCE(tel, ‘登録されていません’) AS tel FROM employee ; name1 name2 tel 山田 次郎 09027109628 佐藤 花子 登録されていません 参考サイト:MySQL 公式サイト(Comparison Operators) PICK UP あわせて読みたいSQL基礎知識 【楽しく学ぶSQL入門】第2章:SELECT文の基礎 【楽しく学ぶSQL入門】第3章:データの制限 【楽しく学ぶSQL入門】第4章:検索結果の加工 【楽しく学ぶSQL入門】第6章:グループ化と集計処理 【楽しく学ぶSQL入門】第7章:副問い合わせ 【楽しく学ぶSQL入門】第8章:結合

【楽しく学ぶSQL入門】第4章:検索結果の加工

システム開発の現場では、データベースから抽出したデータをそのまま使うだけでなく、用途に合わせて見やすく整形したい場面が多々あります。SQLのSELECT文には、取得した結果を柔軟に加工するための便利な指示を追加できます。今回は、実務でも特によく使われる「検索結果の加工キーワード」を3つに厳選して見ていきましょう。 重複行の除外 SELECTの直後にDISTINCTを指定すると、抽出結果の中で内容が重複している行を自動的に1つにまとめて除外してくれます。 ① 例)収支テーブルの費目を重複なく取得する。 コピー SELECT DISTINCT expense FROM income_and_expenditure; expense 飲食費 交通費 娯楽費 行のソート これまでの解説では、データは単にテーブルへ格納されている順に表示されていましたが、実務では「金額の高い順」や「日付の新しい順」に並んでいないと不便なことも多いですよね。そこで活躍するのが、SELECT文の末尾に記述するORDER BY句です。指定した列の値を基準にして、検索結果をきれいに並び替えることができます。 ORDER BYの構文 コピー SELECT 列名 FROM テーブル名 [WHERE 条件式] ORDER BY ソート基準列 [ASC | DESC] 昇順(小さい順・辞書順)を意味する「ASC」と、降順(大きい順・逆順)を意味する「DESC」の2種類から指定します。なお、何も指定しない場合はデフォルトで昇順として扱われるため、ASCは省略しても構いません。記述位置は常にSELECT文の「一番最後」になる点、および並び替えの基準を複数指定したい場合はカンマ区切りで列名を並べればよい点を押さえておきましょう。 ここで、基本的な「昇順(値が小さい順、順番通り)」の並び方の具体的な例を整理しておきます。 ・数字なら…1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ・ひらがななら…五十音順(例えば、大阪の「お」は東京の「と」よりも先に来ますね) ・英語なら…A, B, C, D, E, F, G ・日付なら…過去から未来(古い順)への流れ ② 例)社員テーブルから男性で年齢が高い順に並べて取得する。 コピー SELECT name1, name2, sex_id, age FROM employee WHERE sex_id = 1 ORDER BY age DESC; name1 name2 sex_id age 佐藤 健蔵 1 57 田中 充 1 44 山田 務 1 29 先頭から数件だけを取得する ORDER BY句による並び替えに続けてLIMIT句を組み合わせることで、検索結果として表示する件数をピンポイントで制限できます。 ③ 例)社員テーブルから年齢が高い順に社員を10人取得する。 コピー SELECT name1, name2, age FROM employee ORDER BY age DESC LIMIT 10; name1 name2 age 佐藤 健蔵 57 鈴木 花帆 48 田中 充 44 …(以下、指定した上位10件まで表示) 参考サイト:MySQL 公式サイト(SELECT statement) PICK UP あわせて読みたいSQL基礎知識 【楽しく学ぶSQL入門】第1章:SQLの基礎 【楽しく学ぶSQL入門】第2章:SELECT文の基礎 【楽しく学ぶSQL入門】第3章:データの制限 【楽しく学ぶSQL入門】第5章:単一行関数とデータ型 【楽しく学ぶSQL入門】第6章:グループ化と集計処理 【楽しく学ぶSQL入門】第7章:副問い合わせ

【楽しく学ぶSQL入門】第3章:データの制限

第1章と第2章では、テーブルのデータをすべて取得する基本のSELECT文を扱いました。ただ、実際のシステム開発では、テーブル内に何千万件ものデータが眠っているケースも珍しくありません。膨大な情報から目的のデータだけを絞り込む。そのために条件を指定する仕組みが、今回学ぶ「WHERE句」です。条件を上手に指定して、取得するデータを必要な分だけに制限してみましょう。 比較演算子 WHERE句ではWHEREの後ろに条件式を記述します。 条件式とは、その判定結果が必ず真(TRUE)か偽(FALSE)になる式のこと。多くは「=」や「<」といった記号を含んだ計算式になります。これらの記号を比較演算子と呼びます。 参考サイト:MySQL 公式サイト(Comparison Operators) 基本的な6つの比較演算子 比較演算子 意味 = 左右の値が等しい < 左辺は右辺より小さい > 左辺は右辺より大きい <= 左辺は右辺の値以下 >= 左辺は右辺の値以上 <> or != 左右の値が等しくない IS NULL 列の値が空(NULL)かどうかを判定するときは、IS NULL演算子を使います。逆にNULLではないデータを探すなら、IS NOT NULL演算子の出番。 ① 例)社員テーブルで電話番号を登録していない社員を取得する。 コピー SELECT name1, name2, tel FROM employee WHERE tel IS NULL ; name1 name2 tel 山田 次郎 (NULL) 佐藤 花子 (NULL) ※注意点があります。NULLは「=」や「<>」といった記号では判定できません。必ずIS NULLかIS NOT NULLを使いましょう。 参考サイト:MySQL 公式サイト(Problems with NULL) LIKE演算子 文字列が特定のパターンに一致しているか調べる作業を、パターンマッチングと呼びます。SQLでこれを行うのがLIKE演算子。部分一致による検索を可能にします。 ここで使える記号は「_(アンダーバー)」と「%(パーセント)」の2つ。これらをワイルドカードと呼び、LIKE演算子を掛け合わせた条件指定を曖昧検索と呼びます。 参考サイト:MySQL 公式サイト(Pattern Matching) ② 例)都道府県テーブルから「県」という字で終わる4文字の都道府県を取得する。 コピー SELECT name FROM pref WHERE name LIKE ‘___県’; name 神奈川県 ● 和歌山県 鹿児島県 アンダーバー(_)は、その位置に「任意の1文字が入る」という意味を持ちます。 ③ 例)社員テーブルから姓に「田」という字が含まれる社員を取得する。 コピー SELECT name1 FROM employee WHERE name1 LIKE ‘%田%’ ; name1 江田 南田 田端 パーセント(%)は、「0文字以上の任意の文字列」を表す記号。取得したいデータの桁数や文字の長さが決まっていない場合に重宝します。 BETWEEN演算子 指定した範囲内に値が収まっているかどうか。これを判定する際に便利なのがBETWEEN演算子です。 参考サイト:MySQL 公式サイト(BETWEEN Operator) ④ 例)収支テーブルから出費が0円から1000円までのデータを取得する。 コピー SELECT expense, income_and_expenditure_date, expenditure FROM income_and_expenditure WHERE expenditure BETWEEN 0 AND 1000; expense date expenditure 交通費 2026/05/10 800 飲食費 2026/05/11 1000 娯楽費 2026/05/12 500 この書き方をした場合、0円や1000円といった「指定した境界の値そのもの」も結果に含まれます。 IN演算子 IN演算子は、カッコの中に並べた複数の値のどれかに合致するかを判定します。これを使うと、多くの値と一度に比較できるので記述がすっきりします。 逆のパターン、つまり指定したリストのどれにも合致しないデータを探すときは、NOT IN演算子を選びましょう。 参考サイト:MySQL 公式サイト(IN Operator) ⑤ 例)収支テーブルから費目が飲食費、娯楽費であるデータを取得する。 コピー SELECT expense, income_and_expenditure_date, expenditure FROM income_and_expenditure WHERE expense IN (‘飲食費’, ‘娯楽費’); expense date expenditure 飲食費 2026/05/11 1000 娯楽費 2026/05/12 500 論理演算子 複数の条件を重ねて絞り込みたい場合は、ANDやORといった論理演算子を組み合わせます。 参考サイト:MySQL 公式サイト(Logical Operators) ⑥ 例)社員テーブルからシステム部の男性を取得する。 コピー SELECT group_id, sex_id, name1, name2 FROM employee WHERE group_id = 1 AND sex_id = 1; group_id sex_id name1 name2 1 1 山田 次郎 ANDとORは、左右の両辺に条件式を置いて繋ぐ演算子です。これに対し、右辺の条件だけに作用するNOT演算子というものもあります。NOTを置くと、条件式の結果が反転。真は偽に、偽は真に逆転します。 ⑦ 例)社員テーブルからシステム部の女性(男性ではない)を取得する。 コピー SELECT group_id, sex_id, name1, name2 FROM employee WHERE group_id = 1 AND NOT sex_id = 1; group_id sex_id name1 name2 1 2 佐藤 花子 複数の論理演算子を混ぜるときは、処理される優先順位に注意してください。基本的には、(1) NOT ➔ (2) AND ➔ (3) OR の順番で評価されます。意図した順番で計算させたい場合は、算数と同じように「かっこ ( )」でくくりましょう。評価の優先順位を一番上に引き上げることができます。 例)社員テーブルから部署がシステム部もしくはWeb事業企画部で、年齢が20代もしくは30代の社員を取得する。 どのようなSQLを書けばよいでしょうか…? PICK UP あわせて読みたいSQL基礎知識 【楽しく学ぶSQL入門】第1章:SQLの基礎 【楽しく学ぶSQL入門】第2章:SELECT文の基礎 【楽しく学ぶSQL入門】第4章:検索結果の加工 【楽しく学ぶSQL入門】第5章:単一行関数とデータ型 【楽しく学ぶSQL入門】第6章:グループ化と集計処理

お問い合わせ

CONTACT

業務システムに関するお困りごと、WEBサイトの制作など、
まずはお気軽にお問い合わせください。

会員サイト
CONTACT
06-6305-2278
採用サイトはこちらRECRUIT