この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:6
ページ更新者:T
更新日時:2026-06-11 07:07:02

タイトル: 関数
SEOタイトル: SQL の組み込み関数まとめ(集計 / 文字列 / 日時 / 数値 / 条件 / ユーザー定義)

この記事の要点
  • 集計関数: SUM / COUNT / AVG / MIN / MAX(GROUP BY と組み合わせ)
  • 文字列関数: CONCAT / SUBSTRING / UPPER / LOWER / LENGTH / TRIM
  • 日時関数: NOW / CURDATE / DATE_ADD / DATEDIFF / DATE_FORMAT
  • 数値関数: ROUND / CEIL / FLOOR / ABS / MOD
  • 条件関数: CASE WHEN / COALESCE / NULLIF / IFNULL(MySQL)
  • ユーザー定義関数 (UDF): CREATE FUNCTION で独自関数を定義可能

集計関数 (Aggregate Functions)

複数行の値を 1 つの値に集約する関数。GROUP BY と組み合わせて使うことが多い。

-- 件数
SELECT COUNT(*) FROM orders;            -- NULL も含めた全行
SELECT COUNT(email) FROM users;          -- NULL を除いた件数
SELECT COUNT(DISTINCT category) FROM products;

-- 合計・平均・最大・最小
SELECT SUM(amount), AVG(amount), MIN(amount), MAX(amount)
FROM orders;

-- グループ別集計
SELECT category, COUNT(*) AS cnt, SUM(price) AS total
FROM products
GROUP BY category
HAVING COUNT(*) > 5
ORDER BY total DESC;

-- 文字列を連結する集計(MySQL: GROUP_CONCAT / PostgreSQL: STRING_AGG)
SELECT category, GROUP_CONCAT(name ORDER BY price SEPARATOR ', ')
FROM products GROUP BY category;
関数動作NULL の扱い
COUNT(*)全行数NULL も数える
COUNT(col)非 NULL 件数NULL 除外
SUM(col)合計NULL 除外
AVG(col)平均NULL 除外(分母も)
MIN / MAX(col)最小 / 最大NULL 除外

文字列関数

-- 連結
SELECT CONCAT(first_name, ' ', last_name) AS full_name FROM users;
-- PostgreSQL は || も使える: first_name || ' ' || last_name

-- 部分文字列(1 始まり、長さ指定)
SELECT SUBSTRING(email, 1, 3) FROM users;
-- MySQL: SUBSTRING / SUBSTR / MID
-- PostgreSQL: SUBSTRING(email FROM 1 FOR 3)

-- 大文字・小文字変換
SELECT UPPER(name), LOWER(email) FROM users;

-- 長さ
SELECT LENGTH(name) FROM users;          -- バイト数(MySQL)
SELECT CHAR_LENGTH(name) FROM users;     -- 文字数

-- 前後の空白除去
SELECT TRIM(' Hello ');                  -- 'Hello'
SELECT LTRIM(' Hello'), RTRIM('Hello ');

-- 置換
SELECT REPLACE(email, '@old.com', '@new.com') FROM users;

-- パディング
SELECT LPAD('5', 3, '0');                -- '005'
SELECT RPAD('A', 5, '-');                -- 'A----'

-- 位置検索
SELECT INSTR(email, '@') FROM users;     -- '@' の位置(1 始まり)
SELECT LOCATE('@', email) FROM users;    -- MySQL

-- 文字列を逆順
SELECT REVERSE('Hello');                 -- 'olleH'

日時関数

-- 現在日時
SELECT NOW();                            -- 2026-06-11 12:34:56
SELECT CURDATE(), CURRENT_DATE;          -- 2026-06-11
SELECT CURTIME(), CURRENT_TIME;          -- 12:34:56

-- 加算・減算
SELECT DATE_ADD(NOW(), INTERVAL 7 DAY);
SELECT DATE_SUB(NOW(), INTERVAL 1 MONTH);
SELECT NOW() + INTERVAL 1 HOUR;          -- MySQL の省略形

-- 差分
SELECT DATEDIFF('2026-12-31', '2026-06-11');  -- 日数
SELECT TIMESTAMPDIFF(MONTH, birth, NOW())     -- 月単位 (MySQL)
FROM users;

-- フォーマット
SELECT DATE_FORMAT(NOW(), '%Y/%m/%d %H:%i');  -- '2026/06/11 12:34'
SELECT DATE_FORMAT(NOW(), '%W');              -- 'Thursday'

-- PostgreSQL は TO_CHAR
SELECT TO_CHAR(NOW(), 'YYYY/MM/DD HH24:MI');

-- 一部要素抽出
SELECT YEAR(NOW()), MONTH(NOW()), DAY(NOW()),
       HOUR(NOW()), MINUTE(NOW()), SECOND(NOW());
SELECT EXTRACT(YEAR FROM NOW());         -- 標準 SQL

数値関数

SELECT ROUND(3.567, 2);          -- 3.57(小数 2 桁)
SELECT CEIL(3.2);                -- 4(切り上げ)= CEILING
SELECT FLOOR(3.8);               -- 3(切り捨て)
SELECT TRUNCATE(3.567, 1);       -- 3.5(切り捨て、桁指定)MySQL

SELECT ABS(-7);                  -- 7
SELECT MOD(10, 3);               -- 1(余り)= 10 % 3
SELECT POWER(2, 10);             -- 1024 = POW
SELECT SQRT(16);                 -- 4

SELECT RAND();                   -- 0.0 〜 1.0 の乱数(MySQL)= RANDOM (PG)
SELECT FLOOR(RAND() * 100);      -- 0〜99 の整数乱数

SELECT SIGN(-5), SIGN(0), SIGN(7);  -- -1, 0, 1

条件関数 / NULL 関数

-- CASE WHEN: 標準 SQL
SELECT name,
       CASE
           WHEN score >= 80 THEN 'A'
           WHEN score >= 60 THEN 'B'
           WHEN score >= 40 THEN 'C'
           ELSE 'D'
       END AS grade
FROM students;

-- COALESCE: 最初の非 NULL を返す
SELECT COALESCE(nickname, name, 'Anonymous') FROM users;

-- NULLIF: 2 値が同じなら NULL を返す
SELECT NULLIF(deleted_at, '0000-00-00');

-- MySQL: IFNULL(COALESCE と同等の 2 引数版)
SELECT IFNULL(phone, '不明') FROM users;

-- MySQL: IF
SELECT IF(score > 60, '合格', '不合格') FROM students;

-- SQL Server: ISNULL(MySQL の IFNULL 相当、ただし PG の ISNULL とは別物)
SELECT ISNULL(phone, '不明') FROM users;  -- SQL Server

ユーザー定義関数 (UDF)

独自の関数を作って繰り返し使う処理をカプセル化できます。

-- MySQL: 税込価格計算関数
DELIMITER //
CREATE FUNCTION calc_tax_price(price INT, rate DECIMAL(3,2))
RETURNS INT
DETERMINISTIC
BEGIN
    RETURN FLOOR(price * (1 + rate));
END //
DELIMITER ;

-- 使用
SELECT name, calc_tax_price(price, 0.10) AS tax_inc
FROM products;

-- PostgreSQL: PL/pgSQL
CREATE OR REPLACE FUNCTION calc_tax_price(price INT, rate NUMERIC)
RETURNS INT AS $$
BEGIN
    RETURN FLOOR(price * (1 + rate));
END;
$$ LANGUAGE plpgsql;

ウィンドウ関数 (OVER 句)

SQL:2003 で導入された強力な関数群。集計関数を「グループに集約せず」行ごとに付与できます。

-- カテゴリ別ランキング
SELECT name, category, price,
       RANK()       OVER (PARTITION BY category ORDER BY price DESC) AS rk,
       DENSE_RANK() OVER (PARTITION BY category ORDER BY price DESC) AS dr,
       ROW_NUMBER() OVER (PARTITION BY category ORDER BY price DESC) AS rn
FROM products;

-- 累積合計
SELECT date, amount,
       SUM(amount) OVER (ORDER BY date) AS running_total
FROM sales;

-- 直前・直後の値
SELECT date, amount,
       LAG(amount, 1)  OVER (ORDER BY date) AS prev_amount,
       LEAD(amount, 1) OVER (ORDER BY date) AS next_amount
FROM sales;

FAQ

Q: COUNT(*)COUNT(1) はどちらが速い?
A: 現代の DB(MySQL 8 / PG 12+)では同等。最適化されているので可読性の高い COUNT(*) を推奨。

Q: 文字列連結が CONCAT でうまく動かない
A: NULL が混ざると結果が NULL になる DB が多い(標準 SQL の || も同様)。MySQL の CONCAT_WS(sep, ...) を使うか COALESCE で NULL を空文字に変換してください。

Q: 文字列の長さは LENGTH か CHAR_LENGTH か
A: 日本語など multi-byte 文字を含む場合は CHAR_LENGTH(文字数)。LENGTH はバイト数で UTF-8 では日本語 1 文字が 3 バイトになります。