行を読む:SELECT・WHERE・ORDER BY・LIMIT

多くの検索クエリは、SELECT、WHERE、ORDER BY、LIMIT の4つの句でできています。それぞれの役割と組み合わせ方を見ていきます。

最初のクエリ

クエリが答えるのはひとつの質問です。どの行の、どの列がほしいのか。 いちばん短い聞き方が SELECT *(全部の列)と、FROM にテーブルをひとつ書く形です。

1

-- Every column of every product. Run it with F9 or Ctrl/Cmd + Enter.
SELECT *
FROM products
LIMIT 20;
Planche で実行

結果 — 20 行のうち先頭 5 行

idcategory_idnamedescriptionskupricecoststock_quantityweight_kgattributesis_activecreated_atupdated_at
116Glass Orchard (Paperback ed.)Glass Orchard (Paperback ed.) — built to last.SKU-00001913.72443.951796.18{"color":"green","warranty_months":12,"material":"fabric"}12024-01-13 07:13:522024-01-13 07:13:52
217Luma The GeneLuma The Gene — built to last.SKU-00002332.64161.72835.893{"color":"silver","warranty_months":24,"material":"steel"}12022-06-16 08:45:202022-06-16 08:45:20
321Quill HelmetQuill Helmet — designed for daily use.SKU-00003196.26118.253998.261{"color":"silver","warranty_months":24}12022-08-26 20:06:032022-08-26 20:06:03
416Kite Glass Orchard 3Kite Glass Orchard 3 — built to last.SKU-000041719.68845.912435.263{"color":"silver","warranty_months":24}02022-07-19 11:34:272022-07-19 11:34:27
517The Gene (3rd ed.)The Gene (3rd ed.) — a dependable everyday choice.SKU-00005122.869.53571.898{"color":"red","warranty_months":36,"material":"aluminium"}12022-05-21 10:53:402022-05-21 10:53:40

ブラウザの別タブで Planche が開き、サンプルデータベースを読み込んだ状態でこのクエリが入ります。このページの例はどれも同じタブを使い回します。F9 を押すまで実行はされません。

* は「全列」、LIMIT 20 は「最大20行」を意味します。テーブルの構造を確認するだけなら、products の数千行をすべて取得する必要はありません。取得した行は転送・描画されるためです。

Planche にも結果件数の上限があります(設定 › 安全性 › 行数上限)。ただしクエリに LIMIT を書けば、データベースが読むデータ量も意図どおりに抑えられます。

列を選ぶ

SELECT * はテーブルを確認するときに便利です。必要な内容が決まったら列名を明示してください。結果が読みやすくなり、転送するデータも減ります。

2

SELECT name, sku, price, stock_quantity
FROM products
LIMIT 20;
Planche で実行

結果 — 20 行のうち先頭 5 行

nameskupricestock_quantity
Glass Orchard (Paperback ed.)SKU-00001913.72179
Luma The GeneSKU-00002332.6483
Quill HelmetSKU-00003196.26399
Kite Glass Orchard 3SKU-000041719.68243
The Gene (3rd ed.)SKU-00005122.8357

SELECT に書いた順が結果の列順になります。テーブル側の列順は関係ありません。結果の列名を変えるには AS を使います。

WHERE で行を絞る

SELECT が列を選び、WHERE が行を選びます。条件を受け取り、それが真になる行だけを残します。

3

SELECT name, price, stock_quantity
FROM products
WHERE price > 100
LIMIT 20;
Planche で実行

結果 — 20 行のうち先頭 5 行

namepricestock_quantity
Lean Startup (Deluxe ed.)107.3784
Pixel Sofa108.187
Terra Pillow Pro113.670
Pulse LED Strip114.86480
Brief Answers (3rd ed.)117.96194

比較演算子には =、<>(または !=)、<、<=、>、>= を使います。NULL の比較には別の規則があります。

  • 等価は = ひとつです。== ではありません。
  • NULL とは何も等しくなりません。NULL 同士でもです。WHERE weight_kg = NULL は、重量が記録されていない商品がいくつあっても1行も返しません。書きたい条件は IS NULL / IS NOT NULL です。次のレッスンできちんと扱います。

ORDER BY で並べ替える

ORDER BY を指定しない場合、返る行の順序は保証されません。順序が必要なら明示してください。データやインデックスが変われば、たまたま見えていた順序も変わります。

4

SELECT name, price
FROM products
ORDER BY price DESC
LIMIT 20;
Planche で実行

結果 — 20 行のうち先頭 5 行

nameprice
Glide GPS Watch Pro2484.4
Terra 3D Puzzle2481.77
Aria Castle Kit2479.41
Aria LED Strip Pro2463.41
Nova Brief Answers2445.49

DESC は大きい順、ASC(既定)は小さい順です。ORDER BY price DESC と LIMIT 20 を組み合わせると、価格の高い順に20件を取得できます。まず全体を並べ替え、その後で先頭20行を取ります。

Planche では結果グリッドの列見出しをクリックして並べ替えることもできます。昇順、降順、解除の順に切り替わり、サーバー側で再取得されます。

複数の列で並べ替える

並べ替えキーを複数指定すると、前のキーで同じ値だった行を次のキーで並べ替えます。

5

SELECT category_id, name, price
FROM products
ORDER BY category_id, price DESC
LIMIT 30;
Planche で実行

結果 — 30 行のうち先頭 5 行

category_idnameprice
2Aria Notebook2116.4
2Ember Laptop Plus2087.98
2Sol Notebook1982.34
2Sol Ultrabook1942.47
2Nimbus Ultrabook1933.06

このクエリはカテゴリ順に並べ、その中では価格の高い商品を先に表示します。

式と別名

SELECT に書けるのは列だけではありません。四則演算でも関数呼び出しでも、行ごとに値を作るものなら書けます。そして AS がその結果に名前を付けます。

6

SELECT name,
       price,
       cost,
       ROUND(price - cost, 2) AS margin
FROM products
WHERE is_active = 1
ORDER BY margin DESC
LIMIT 15;
Planche で実行

結果 — 15 行のうち先頭 5 行

namepricecostmargin
Ember Tab Plus2412.93984.941427.99
Aria LED Strip Pro2463.411098.691364.72
Luma Denim Jacket Pro2357.59993.241364.35
Drift A Winter Letter2422.51082.431340.07
Nova Brief Answers2445.491108.091337.4

ROUND(price - cost, 2) AS margin は、テーブルのどこにも存在しない列を計算しています。そして margin という名前は ORDER BY で使えます。しかし WHERE では使えません。ここは本当によく引っかかるところです。理由は、データベースが句を評価する順序にあります。

FROM  ->  WHERE  ->  SELECT  ->  ORDER BY  ->  LIMIT

ORDER BY が動くころには SELECT が margin を作り終えています。WHERE が動く時点ではまだ存在しないので、WHERE margin > 50 はエラーになります。式をもう一度書くか、クエリ全体をもうひとつのクエリで包むしかありません。この順序は覚えておいてください。WHERE がグループ化の前に行を絞り、HAVING が後で絞る理由も同じ順序で説明がつきます。それは2つ先のレッスンです。

ここまでで書けるもの

この4つの句だけでも、現実の質問にかなり答えられます。高い順に20商品、在庫切れの一覧、販売中の商品で利益率が高いもの。まだできないのは、2つのテーブルにまたがる質問です。どの顧客がどの注文をしたか。そのための道具が結合です。

次に進む前に、上の例題の数字や列名を書き換えて実行し直してみてください。グリッドはその場で更新されるので、試す速度はかなり速いはずです。

自分で書いてみる

  1. 販売中の商品のうち、安いほうから10件。名前と価格だけを表示してください。(is_active は販売中なら1です。)

    答えを見る

    答えを見る

    SELECT name, price
    FROM products
    WHERE is_active = 1
    ORDER BY price
    LIMIT 10;
    Planche で実行

    結果 — 10 行のうち先頭 5 行

    nameprice
    Clean Code (2nd ed.)6.89
    Nimbus Desk Max7.21
    Drift Castle Kit Max17.35
    Pixel Laptop18.46
    Terra Dumbbell Set19.8

    3つの句がひとつずつ仕事をしています。WHERE が販売していない商品を落とし、ORDER BY price が安いものを先頭に置き(昇順が既定なのでキーワードは要りません)、LIMIT 10 がそこで打ち切ります。

  2. 商品ごとの在庫金額はいくらですか。名前、数量、そして価格 × 数量を小数2桁で丸めた値を、大きい順に表示してください。

    答えを見る

    答えを見る

    SELECT name,
           stock_quantity,
           ROUND(price * stock_quantity, 2) AS stock_value
    FROM products
    ORDER BY stock_value DESC
    LIMIT 10;
    Planche で実行

    結果 — 10 行のうち先頭 5 行

    namestock_quantitystock_value
    Luma Boots4921042454.52
    Glide GPS Watch Pro4141028541.6
    Brief Answers (Deluxe ed.)434988448.02
    Brief Answers (Hardcover ed.)413980879.13
    Vega Field Watch464975221.28

    3列目はテーブルのどこにも存在しません。AS stock_value がその名前を与え、ORDER BY は SELECT の後に動くので、その名前で並べ替えられます。