Q1次のうち、SELECT 10 % 3;の結果として正しいものはどれですか。
関数 ① — 算術演算・文字列連結・日付関数
この記事は、基礎から複雑なSQL,SQLチューニングまでSQLの実践的なスキルを1からマスターする「SQL入門講座の一部」です。
算術演算子 + - * / %、|| とCONCATによる文字列連結、現在日時の取得や年月の抽出まで、CSVの社員データで実行しながら関数の基礎を押さえます。
本記事で使うデータ — staff テーブル
ここから 3 本にわたって、SQL に組み込まれている関数(function)を学びます。1 本目は算術演算・文字列連結・日付関数の 3 カテゴリで、いずれもSELECTの列リストで使うことが多い式です。
題材は CSV から自動ロードするstaffテーブル(10 行: id / name / birthday / city / salary)です。salary を使った金額計算、name と city を使った文字列連結、birthday を使った日付フォーマットなど、本記事の 4 演習で多角的に使い分けます。
算術演算子 — +, -, *, /, %
数値列を使った計算には+ - * / %の 5 つの算術演算子が使えます。SQL はSELECTの列リストの中で式を書けるので、テーブルから取り出した値をその場で計算した結果を別の列として返せます。また、AS 別名で結果列に名前を付けると、画面表示や後段プログラムで扱いやすくなります。
割り算/は整数同士だと整数結果になる DB(PostgreSQL / SQL Server など)と、自動的に小数になる DB(MySQL / 本講座のコンソール = SQLite)があります。
-- 1) テーブルを使わない単純な計算
SELECT 1 + 1; -- 2
SELECT 10 - 3; -- 7
SELECT 3 * 4; -- 12
SELECT 10.0 / 3; -- 3.333...
SELECT 10 % 3; -- 1
-- 2) 列を使った計算(10 % 昇給後の年収)
SELECT name, salary, salary * 1.1 AS next_year_salary
FROM staff;
-- 3) 月給を計算(年俸 / 12)
SELECT name, salary / 12 AS monthly_salary FROM staff;
+ - * / %の 5 つは、ほとんどのプログラミング言語と同じ意味で使えます。文字列連結 — `||`と`CONCAT()`
複数の文字列を 1 つにつなぐ操作を連結といいます。連結には書き方が 2 通りあり、本講座のコンソール (SQLite) と PostgreSQL / Oracle / SQL Server では||(縦棒 2 つ)演算子、MySQL ではCONCAT()関数を使います。SQLite は||とCONCAT()の両方をサポートするので、本記事は移植性の高いCONCAT()を中心に進めます。
途中に区切り文字(': 'や' / ')を挟むことで、nameとcityを「Alice Tanaka / Tokyo」のように見やすい 1 列にまとめられます。レポートや CSV 出力で「複数列を 1 列に結合した形でほしい」という場面で重宝する関数です。
-- 1) || 演算子(SQLite / PostgreSQL / Oracle)
SELECT name || ' (' || city || ')' AS label FROM staff;
-- 2) CONCAT 関数(MySQL / SQLite 3.40+ / PostgreSQL)
SELECT CONCAT(name, ' (', city, ')') AS label FROM staff;
-- どちらも結果は同じ
-- → Alice Tanaka (Tokyo) / Bob Suzuki (Osaka) / ...
`||`と`CONCAT()`のどちらを選ぶか
移植性で選ぶならCONCAT()が安全です。SQLite / MySQL / PostgreSQL / SQL Server(2012+)/ Oracle のすべてで動きます。||は SQL 標準ですが、MySQL では既定で論理 OR の意味になるため、本番が MySQL の可能性がある環境ではCONCAT()を選ぶと書き換えなしで通用します。
NULL の扱いには差があり、NULL || 'A'は||だと NULL になります。一方CONCAT(NULL, 'A')は MySQL では空文字を返し、PostgreSQL では NULL を返すなど挙動が分かれます。連結対象に NULL が混じる可能性があるときは、COALESCE(列, '')で NULL を空文字に変換してから連結するのが安全です(COALESCE は本連載 3 本目で扱います)。
日付関数 — 現在日時とフォーマット
「いま登録された日時を入れたい」「生年月日から年だけ取り出したい」のように、日付・時刻を扱うときに使うのが日付関数です。日付関数はDB ごとに名前と書き方が違うカテゴリの代表格で、本講座のコンソール (SQLite) と MySQL では呼び出し方がかなり違います。
本講座では SQLite のdatetime('now') / date('now') / strftime('フォーマット', 値)を中心に演習し、MySQL のNOW() / CURDATE() / DATE_FORMAT(値, 'フォーマット')は対応表で並べて紹介します。フォーマット文字列('%Y'で年、'%m'で月、'%d'で日 など)は両 DB で共通の書式を使うので、書式部分だけは横展開できます。
-- 本講座のコンソール (SQLite) での書き方
-- 1) 現在日時 / 現在日付
SELECT datetime('now') AS current_dt, date('now') AS current_d;
-- 2) フォーマット指定(年だけ / 年月だけ)
SELECT strftime('%Y', '1990-04-15') AS year_only; -- '1990'
SELECT strftime('%Y-%m', '1990-04-15') AS year_month; -- '1990-04'
-- 3) 列に対するフォーマット
SELECT name, strftime('%Y', birthday) AS birth_year FROM staff;
-- 参考: MySQL で同じことを書く場合
-- SELECT NOW(), CURDATE();
-- SELECT DATE_FORMAT(birthday, '%Y') FROM staff;
| 用途 | 本講座のコンソール (SQLite) | MySQL |
|---|---|---|
| 現在日時 | datetime('now') | NOW() |
| 現在日付 | date('now') | CURDATE() |
| 年だけ取り出す | strftime('%Y', d) | DATE_FORMAT(d, '%Y') |
| フォーマット指定 | strftime('%Y-%m-%d', d) | DATE_FORMAT(d, '%Y-%m-%d') |
理解度チェック
まずは1問ずつ答えてみましょう。
Q2本講座のコンソールで「nameとcityをAlice Tanaka (Tokyo)のような形にまとめて 1 つの列で取り出す」書き方として正しいものはどれですか。
Q3本講座のコンソール (SQLite) でbirthday列から「年(4 桁)だけ」を取り出すときに使う書き方はどれですか。