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

タイトル: 関数
SEOタイトル: MySQL 関数完全リファレンス — 文字列・日付・集計

この記事の要点
  • 文字列: CONCAT / SUBSTRING / REPLACE / LENGTH / LOWER / UPPER / TRIM
  • 数値: ROUND / FLOOR / CEILING / ABS / MOD / POW / SQRT
  • 日付: NOW / CURDATE / DATE_FORMAT / DATE_ADD / DATEDIFF / TIMESTAMPDIFF
  • 集計: COUNT / SUM / AVG / MAX / MIN / GROUP_CONCAT
  • 条件: IF / CASE WHEN / COALESCE / IFNULL / NULLIF
  • ウィンドウ関数 (8.0+): ROW_NUMBER / RANK / DENSE_RANK / LAG / LEAD

文字列関数

-- 連結
SELECT CONCAT('Hello, ', name, '!') FROM users;
SELECT CONCAT_WS('-', '2024', '01', '15');    -- '2024-01-15' (区切り付き)

-- 部分文字列 (1 始まり)
SELECT SUBSTRING('hello world', 7, 5);        -- 'world'
SELECT SUBSTRING_INDEX('a,b,c,d', ',', 2);    -- 'a,b'

-- 置換
SELECT REPLACE('foo bar foo', 'foo', 'baz');  -- 'baz bar baz'

-- 長さ (バイト)
SELECT LENGTH('あいう');     -- 9 (UTF-8 で 3 バイト × 3)
SELECT CHAR_LENGTH('あいう'); -- 3 (文字数)

-- 大小変換
SELECT LOWER('Hello'), UPPER('Hello');

-- 空白除去
SELECT TRIM('  hello  '), LTRIM('  hello'), RTRIM('hello  ');
SELECT TRIM(BOTH '0' FROM '00abc00');         -- 'abc'

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

-- 位置検索
SELECT INSTR('hello world', 'world');         -- 7
SELECT LOCATE('o', 'hello', 5);               -- 5 (5 文字目から検索)

数値関数

-- 四捨五入
SELECT ROUND(3.7);           -- 4
SELECT ROUND(3.14159, 2);    -- 3.14

-- 切り捨て・切り上げ
SELECT FLOOR(3.7);           -- 3
SELECT CEILING(3.2);         -- 4
SELECT TRUNCATE(3.789, 1);   -- 3.7 (切り捨て桁指定)

-- 絶対値・剰余
SELECT ABS(-5);              -- 5
SELECT MOD(10, 3);           -- 1
SELECT 10 % 3;               -- 1 (同じ)

-- 累乗・平方根
SELECT POW(2, 10);           -- 1024
SELECT SQRT(16);             -- 4

-- 乱数
SELECT RAND();               -- 0〜1
SELECT FLOOR(RAND() * 100);  -- 0〜99

日付・時刻関数

-- 現在時刻
SELECT NOW();           -- '2026-06-10 12:34:56'
SELECT CURDATE();       -- '2026-06-10'
SELECT CURTIME();       -- '12:34:56'
SELECT UNIX_TIMESTAMP(); -- 1749553496

-- フォーマット
SELECT DATE_FORMAT(NOW(), '%Y/%m/%d %H:%i');   -- '2026/06/10 12:34'
SELECT DATE_FORMAT(NOW(), '%Y年%m月%d日');

-- パース
SELECT STR_TO_DATE('2026/06/10', '%Y/%m/%d');

-- 加減算
SELECT DATE_ADD(NOW(), INTERVAL 7 DAY);          -- 7 日後
SELECT DATE_SUB(NOW(), INTERVAL 1 MONTH);        -- 1 ヶ月前
SELECT NOW() + INTERVAL 1 HOUR;                  -- 1 時間後

-- 差分
SELECT DATEDIFF('2026-06-10', '2026-01-01');     -- 160 (日数)
SELECT TIMESTAMPDIFF(MONTH, '2025-01-01', '2026-06-10');  -- 17 (月数)
SELECT TIMESTAMPDIFF(YEAR,  '1990-04-15', CURDATE());     -- 年齢計算

-- 抜き出し
SELECT YEAR(NOW()), MONTH(NOW()), DAY(NOW());
SELECT DAYOFWEEK(NOW());   -- 1=日, 2=月, ..., 7=土
SELECT DAYNAME(NOW());     -- 'Wednesday'

-- 月末
SELECT LAST_DAY(NOW());

DATE_FORMAT のフォーマット

記号意味
%Y年 4 桁2026
%y年 2 桁26
%m月 (01-12)06
%c月 (1-12)6
%d日 (01-31)10
%e日 (1-31)10
%H時 (00-23)14
%h / %I時 (01-12)02
%i分 (00-59)30
%s秒 (00-59)45
%W曜日名Wednesday
%a曜日略Wed

集計関数

SELECT
    COUNT(*),               -- 全件
    COUNT(email),           -- email が NULL 以外の件数
    COUNT(DISTINCT user_id),
    SUM(amount),
    AVG(amount),
    MAX(created_at),
    MIN(price),
    GROUP_CONCAT(name SEPARATOR ', ')   -- 文字列連結 (デフォルト 1024 文字)
FROM orders
WHERE status = 'paid';

-- GROUP BY と合わせて
SELECT user_id, COUNT(*) AS cnt, SUM(amount) AS total
FROM orders
GROUP BY user_id
HAVING total > 10000;

条件関数

-- IF (式, 真の値, 偽の値)
SELECT IF(score >= 60, '合格', '不合格') FROM students;

-- CASE WHEN
SELECT name,
    CASE
        WHEN score >= 90 THEN 'A'
        WHEN score >= 80 THEN 'B'
        WHEN score >= 60 THEN 'C'
        ELSE 'F'
    END AS grade
FROM students;

-- NULL ハンドリング
SELECT COALESCE(nickname, name, 'no name') FROM users;
-- 最初の非 NULL を返す

SELECT IFNULL(phone, 'none') FROM users;
-- 1 つだけ。NULL なら 'none'

SELECT NULLIF(a, b);     -- a = b なら NULL、違えば a

ウィンドウ関数 (MySQL 8.0+)

-- ユーザー別売上ランキング
SELECT
    user_id,
    order_no,
    amount,
    ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY amount DESC) AS rn,
    RANK()       OVER (PARTITION BY user_id ORDER BY amount DESC) AS rk,
    DENSE_RANK() OVER (PARTITION BY user_id ORDER BY amount DESC) AS drk
FROM orders;

-- 前後の行
SELECT
    date,
    sales,
    LAG(sales, 1)  OVER (ORDER BY date) AS prev_sales,
    LEAD(sales, 1) OVER (ORDER BY date) AS next_sales,
    sales - LAG(sales, 1) OVER (ORDER BY date) AS diff
FROM daily_sales;

-- 移動平均
SELECT date, sales,
    AVG(sales) OVER (
        ORDER BY date
        ROWS BETWEEN 6 PRECEDING AND CURRENT ROW
    ) AS ma_7days
FROM daily_sales;

JSON 関数 (5.7+)

-- 値取り出し
SELECT JSON_EXTRACT(meta, '$.theme') FROM user_settings;
SELECT meta->>'$.theme'              FROM user_settings;  -- 同じ (8.0+)

-- 更新
UPDATE user_settings
SET meta = JSON_SET(meta, '$.theme', 'dark')
WHERE user_id = 1;

-- キー存在
SELECT * FROM user_settings WHERE JSON_CONTAINS_PATH(meta, 'one', '$.theme');

-- 配列に追加
UPDATE user_tags SET tags = JSON_ARRAY_APPEND(tags, '$', 'new');

FAQ

Q: LENGTHCHAR_LENGTH の違い
A: LENGTH はバイト数、CHAR_LENGTH は文字数。UTF-8 で日本語は 3 バイト、絵文字は 4 バイト。

Q: NOW() と CURRENT_TIMESTAMP の違い
A: 同じ。エイリアス関係。

Q: GROUP_CONCAT が途中で切れる
A: group_concat_max_len が 1024 バイト。SET SESSION group_concat_max_len = 1000000 で拡張。