【SQL】検索結果を加工する主なキーワードと使い方まとめ
はじめに
『スッキリわかるSQL入門 第2版』で学んだ、SELECT文によって抽出した結果を加工するために使用できるキーワードについて、メモとしてまとめました。
SELECTによる2段階処理
1. 抽出
2. 加工
検索結果を加工する主なキーワード
DISTINCTORDER BY-
OFFSET-FETCH UNIONEXCEPTINTERSECT
加工のプロセスで「並び替え」や「重複行の削除」など
検索結果を加工する主なキーワード
1. DISTINCT:重複行を除外する
SELECT文の最初に記述する
-- DISTINCTなし
SELECT 入金額
FROM 家計簿
-- DISTINCTあり
SELECT DISTINCT 入金額
FROM 家計簿
データの種類を取得する場合に役立つ
2. ORDER BY:結果を並び替える
SELECT 列名
FROM テーブル名
WHERE 条件式
ORDER BY 並び替えの基準 [ASC | DESC];
SELECT文の最後に記述する
指定した列の値を基準として検索結果を並び替え
並び替えの基準とする列名と並び順を指定する
- 昇順:
ASC - 降順:
DESC
※ 初期値は昇順のため、省略すると結果は昇順になる
※ ORDER BY句に文字列を指定すると、DBMSに設定された照合順序(文字コード順、アルファベット順など)を基準として並び替えられる
※ 並び替えは便利ではあるが、DBMSにとってはかなり負荷のかかる作業
性能上のボトルネックになることを防ぐため、インデックスの使用が推奨されるが、一時的に大量のメモリを消費する可能性がある。
複数の列を基準にした並び替え
複数の列をカンマで区切って指定することで、最初に指定された列で並び替えて同じ値が複数行存在する場合は、次に指定された列で並び替えが行われる(同順位がある場合は続きで記述された列で並び替え)
= 指定したそれぞれの列に対して昇順・降順の選択ができる
SELECT *
FROM 家計簿
ORDER BY 入金額 DESC, 出金額 DESC
列番号を指定した並び替え
列番号:選択列リストにおける列の順番のことで、SELECT命令に記述した順に1から数える
SELECT *
FROM 家計簿
ORDER BY 4 DESC, 5 DESC
テーブルの全列を指定するアスタリスク「*」を選択列リストに使った場合も、実際に取得対象となる列に置き換えた列番号を指定する
※ ただし、可読性・保守性の観点から、カラム名を記述することが推奨される
※ ORDER BY句における列指定に列番号を用いる場合、SELECT文の選択列リストの記述を修正すると、並び替えの結果にも影響が及ぶ点には注意が必要
-- 入金額 → 出金額
SELECT 入金額, 出金額
FROM 家計簿
ORDER BY 1 DESC, 2 DESC
-- 出金額 → 入金額
SELECT 出金額, 入金額
FROM 家計簿
ORDER BY 1 DESC, 2 DESC
3. OFFSET - FETCH:先頭から数行だけ取得
SELECT 列名
FROM テーブル名
ORDER BY 列名 [ASC | DESC]
OFFSET 先頭から除外する行数 ROWS
FETCH NEXT 取得行数 ROWS ONLY
検索結果の全行ではなく、並び替えた結果の一部の行だけ取得する
ORDER BY句の後にOFFSET - FETCHを記述する
ORDER BY は OFFSET や LIMIT よりも前に書かないといけない
-
OFFSET句には、先頭から除外したい行数を記述する
省略はできないため、1件目から取得したい場合には0を指定すること -
FETCH句には、取得したい行数を指定する
省略すると、該当するすべての行が抽出される -
NEXT句は、対象外の最後の行(OFFSETで飛ばした部分)の次の行から取得を開始することを意味する
SELECT 費目, 出金額
FROM 家計簿
ORDER BY 出金額 DESC
OFFSET 0 ROWS
FETCH NEXT 3 ROWS ONLY
※ OFFSET - FETCHに対応していないDBMSも存在する
SELECT 費目, 出金額
FROM 家計簿
ORDER BY 出金額 DESC
LIMIT 3
-- OFFSETで読み飛ばす行数を指定することも可能 --
SELECT 費目, 出金額
FROM 家計簿
ORDER BY 出金額 DESC
OFFSET 3 --上位3つ飛ばし--
LIMIT 3
SELECT TOP(3) 費目, 出金額
FROM 家計簿
ORDER BY 出金額 DESC
集合演算子
長年データベースを利用していると、テーブルに格納する行数(レコード数)が膨大になり、処理が遅くなってしまう恐れがある。
◎ テーブル分割をすることで処理効率を改善することができる
テーブル分割した後、それぞれのテーブルに対してSQL文を2回実行するのは面倒。
構造がよく似た複数のテーブルに SELECT 文をそれぞれに送り、その結果を組み合わせたい場合に集合演算子を活用することにより、1つのSQL文で目的を達成することができる。
集合演算は、SELECT 命令によって抽出した結果表を1つのデータの集合と捉え、その結果同士を足し合わせたり、共通部分を探したりといった様々な演算を行なってくれる仕組み。
※https://iqraanwar.medium.com/09-set-theory-for-sql-joins-ac199f4aa335 より画像引用
集合演算は、選択列リストの組み合わせで計算されます。
「選択列リストの組み合わせで計算される」とは、SELECT 句に書かれた列すべての組み合わせ(行全体)を使って一致判定するという意味。1列でも違えば別の行として扱われます。
※ 選択列リスト:SQL文の中で指定された列名の並び
集合演算子は複数の検索結果を1つの結果表として返してくれるが、それぞれの検索結果の列数が異なったり、データ型がバラバラだったりすると、DBMSは1つの結果表にまとめることができない。
そのため、それぞれのテーブルの列数とデータ型をぴったり一致させる必要がある。
◎ SELECTの結果を集合演算子としてまとめるときは、選択列リストの列数とそれぞれのデータ型が一致していなければならない
→ 列数とデータ型さえ一致していれば、全く異なるテーブルや列でもひとまとめにして抽出することができる
「各SELECT文で選択した列の数と、その順番・データ型」が一致している必要がある」とは、「テーブルの列構成が同じである必要がある」わけではなく、あくまでも SELECT で取り出す列(結果列)の構成が一致していればOK という意味
UNION演算子:和集合
2つの検索結果を足し合わせたもの
和集合:各集合に存在するすべての要素の集合なので、A UNION B でも B UNION A でも結果に影響はない
SELECT 文1
UNION (ALL)
SELECT 文2
-
UNION単体:重複行は1行にまとめる -
UNION ALL:重複行をすべてそのまま返す
1つのテーブルに格納されたデータを複数の異なる条件で抽出したい場合にもUNIONは使用できる
それぞれのWHERE条件を記述した SELECT 文を用意し、UNION で1つのSQL文としてまとめることで、SQLの実行回数を抑えることができる
集合演算子でORDER BY句を使うときの注意点
ORDER BY句は最後のSELECT文に記述すること-
列番号以外による指定(列名や
ASによる別名)の場合、1つ目のSELECT文のものを指定すること
集合演算(UNIONなど)は、複数のSELECT文の結果を1つの結果表としてまとめて返す操作です。
しかし、ORDER BY句はこの「最終的な結果」に対して並べ替えをするため、どの列を基準に並べ替えるかを、1つ目のSELECT文の列名や別名に基づいて指定する必要があります。
--OK--
--ORDER BY '名前' で使われている '名前' は、1つ目のSELECT文で 'name AS 名前' として定義されているから--
SELECT name AS 名前, age AS 年齢 FROM students
UNION
SELECT username, years_old FROM users
ORDER BY 名前;
--NG--
SELECT name, age FROM students
UNION
SELECT username AS 名前, years_old FROM users
ORDER BY 名前;
数が一致しないSELECT文を繋げるテクニック
選択列リストの数が合わないSELECT文で、どうしても集合演算子を使いたい場合、足りない方の選択列リストにNULLを追加することで、数を一致させることができる
EXCEPT(MINUS)演算子:差集合
最初の検索結果から次の検索結果と重複する部分を取り除いたもの
ある集合と別の集合の差
あるSELECT文の検索結果に存在する行から、別のSELECT文の検索結果に存在する行を差し引いた集合のこと
※和集合とは考え方が異なる。1+2 と 2+1の結果は同じだが、1-2 と 2-1の結果は異なるのと同じ
SELECT 文1
EXCEPT (ALL)
SELECT 文2
※Oracle DB ではMINUSを使用する
EXCEPT ALL:重複した行を1行にまとめず、そのまま返す
◎ SELECTの結果を集合演算子としてまとめるときは、選択列リストの列数とそれぞれのデータ型が一致していなければならない
集合演算子でORDER BY句を使うときの注意点
ORDER BY句は最後のSELECT文に記述すること-
列番号以外による指定(列名や
ASによる別名)の場合、1つ目のSELECT文のものを指定すること
集合演算(UNIONなど)は、複数のSELECT文の結果を1つの結果表としてまとめて返す操作です。
しかし、ORDER BY句はこの「最終的な結果」に対して並べ替えをするため、どの列を基準に並べ替えるかを、1つ目のSELECT文の列名や別名に基づいて指定する必要があります。
INTERSECT演算子:積集合
2つの検索結果で重複するもの
積集合:2つのSELECT文に共通する行を集めた集合
和集合同様、どの順番でSELECT文を記述しても結果は変わらない
SELECT 列名
FROM テーブル名
INTERSECT (ALL)
SELECT 列名
FROM テーブル名
◎ SELECTの結果を集合演算子としてまとめるときは、選択列リストの列数とそれぞれのデータ型が一致していなければならない
集合演算子でORDER BY句を使うときの注意点
ORDER BY句は最後のSELECT文に記述すること-
列番号以外による指定(列名や
ASによる別名)の場合、1つ目のSELECT文のものを指定すること
集合演算(UNIONなど)は、複数のSELECT文の結果を1つの結果表としてまとめて返す操作です。
しかし、ORDER BY句はこの「最終的な結果」に対して並べ替えをするため、どの列を基準に並べ替えるかを、1つ目のSELECT文の列名や別名に基づいて指定する必要があります。
参考文献
『スッキリわかるSQL入門 第2版』




Discussion