MariaDB講座 / SELECTで列・別名・計算・DISTINCTを指定する

SELECTは選んだ列と計算結果を読み取り、ASは出力列に名前を付けます。DISTINCTは選択した値の組み合わせの重複を結果から取り除き、元の列名や保存行は変更しません。

保存構造と結果の形を分ける

SELECTの式が表示する列、FROMが読み取る表を指定します。SELECT *より列を明示すると、表へ列を追加した後もアプリケーションや出力ファイルの契約を確認しやすくなります。price * stockは行ごとの値で、全商品の合計は集計関数の役割です。

出力順を保証するにはORDER BYを明示します。一度の表示で追加順に見えても、その順番が保証されるわけではありません。

同じ条件の六商品を用意する

SQLファイルの実行方法でcourse_userとして学習サーバーへ接続し、SELECT VERSION(), DATABASE();とSHOW TABLES;で対象を確認します。通常例はUTF-8の.sqlファイルで実行できます。同名の実習表がある場合は定義と行を調べ、必要なデータを保存してから判断します。既存のアプリケーション表を置き換えません。

USE shopcourse;
CREATE TABLE products_14_lab (
  product_id INT NOT NULL AUTO_INCREMENT,
  product_name VARCHAR(100) NOT NULL,
  category VARCHAR(30) NOT NULL,
  price DECIMAL(10,2) NOT NULL,
  stock INT NOT NULL DEFAULT 0,
  note VARCHAR(100) NULL DEFAULT NULL,
  PRIMARY KEY (product_id),
  CONSTRAINT ck_p14_price CHECK (price >= 0),
  CONSTRAINT ck_p14_stock CHECK (stock >= 0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO products_14_lab
  (product_id, product_name, category, price, stock, note)
VALUES (1, '노트', '문구', 3500.00, 20, NULL),
  (2, '볼펜', '문구', 1500.00, 0, ''),
  (3, '머그컵', '생활', 8000.00, 12, '선물 포장'),
  (4, '스탠드', '생활', 25000.00, 5, NULL),
  (5, '파일', '문구', 1500.00, 50, ''),
  (6, '케이블', '전자', 8000.00, 0, '호환 확인');

SQLの文字列はUTF-8実習の条件をそろえるため、原文の韓国語サンプルを維持しています。ID1~6はノート、ペン、マグカップ、スタンドライト、ファイル、ケーブルです。分類は文具・生活用品・電子用品で、結果はIDと数値を基準に照合できます。ファイルはUTF-8、接続もutf8mb4を使ってください。

同じ価格や分類、在庫0、NULLを意図して含めています。SELECTを繰り返しても、この初期データは変更されません。

別名と行ごとの金額を確認する

最初の例は、商品名と販売価格を意味する韓国語の出力別名です。保存列product_nameとpriceが改名されるわけではありません。

SELECT product_id, product_name AS 상품명, price AS 판매가
FROM products_14_lab ORDER BY product_id;

空白を含む識別子にはバッククォートを使い、文字列リテラルと区別します。次は各行の在庫評価額を計算します。

SELECT product_id, product_name, price, stock,
       price * stock AS inventory_value
FROM products_14_lab ORDER BY product_id;

ID1~6のinventory_valueは70000、0、96000、125000、75000、0です。現在価格×在庫の単純な計算で、原価・税・割引の業務定義を決める式ではありません。

DISTINCTは選んだ全列の組に働く

二つの結果を比較します。

SELECT DISTINCT category FROM products_14_lab ORDER BY category;
SELECT DISTINCT category, price
FROM products_14_lab ORDER BY category, price;

categoryだけなら三種類、categoryとpriceなら五組です。文具・1500の組が一つになり、主キーまで選ぶと六行すべて残ります。DISTINCTは最初の列だけを加工するものでも、分類ごとの代表商品を選ぶものでもありません。代表一行が必要なら、並び順や選択基準を別に定めます。

WHEREの式と出力別名を区別する

在庫評価額100000以上を読みます。

SELECT product_name, price * stock AS inventory_value
FROM products_14_lab
WHERE price * stock >= 100000
ORDER BY inventory_value DESC, product_id ASC;

ID4だけが125000で該当します。同じSELECTで作った別名は通常そのWHEREで使えないため、WHEREには式を書き、ORDER BYには別名を使っています。これは論理的な理解であり、最適化器の物理的アクセス順を断定する説明ではありません。

Unknown columnならDESCRIBE、つづり、列別名とDBを確認します。計算がNULLなら入力を調べ、勝手に0にしません。DISTINCTで結果が減っても、保存行が消えたわけではありません。

実習の再作成

やり直すときは、選択中のDB・実際の表定義・保存行を確認し、必要なものをバックアップします。削除してよいこの記事の実習表だけに次を実行します。DROP TABLEは定義と行を削除し、通常のROLLBACKでは戻せないため、トランザクションの実験とは分けます。

DROP TABLE shopcourse.products_14_lab;

関連する公式リファレンス