【SQL】文字数をカウントして多い順・少ない順でソートする方法|LENGTH・CHAR_LENGTH・LEN・RDBMS別の違い

データベースに格納された文字列の文字数をカウントし、その結果を多い順(降順)や少ない順(昇順)でソートすることは、データ分析やデータクレンジングで頻繁に使うテクニックです。

この記事では、LENGTHCHAR_LENGTHLENなど文字数を取得する関数の使い方から、ORDER BYでのソート、WHERE句でのフィルタリングGROUP BY + HAVINGでの集計バイト数と文字数の違いRDBMS間の比較まで、実務で必要な知識を網羅的に解説します。

この記事で学べること

  • LENGTH / CHAR_LENGTH で文字数をカウントする基本
  • LEN(SQL Server)との違い
  • 文字数の多い順(DESC)・少ない順(ASC)でソート
  • WHERE句での文字数フィルタリング
  • GROUP BY + LENGTH で文字数別に集計
  • HAVINGでの文字数条件
  • バイト数と文字数の違い(LENGTHB, DATALENGTH)
  • TRIMとの組み合わせ
  • NULL・空文字列の扱い
  • MySQL・PostgreSQL・SQL Server・Oracle のRDBMS間比較
  • よくあるエラーと対処法
  • 実務パターン(データクレンジング、バリデーション等)
スポンサーリンク
  1. サンプルテーブル
  2. LENGTH / CHAR_LENGTH で文字数をカウントする基本
    1. CHAR_LENGTH(文字数を取得)
    2. LENGTH(バイト数を取得)
  3. LEN(SQL Server)との違い
  4. 文字数の多い順・少ない順でソートする
    1. 文字数の多い順(降順 / DESC)
    2. 文字数の少ない順(昇順 / ASC)
    3. エイリアスを使ったソート
  5. WHERE句で文字数をフィルタリングする
    1. 文字数が指定値以上のデータを取得
    2. 文字数の範囲を指定(BETWEEN)
    3. description の文字数でフィルタリング
  6. GROUP BY + CHAR_LENGTH で文字数別に集計する
    1. 商品名の文字数ごとの件数
    2. 文字数の範囲別に集計(CASE式)
  7. HAVING で文字数の集計結果をフィルタリング
    1. 2件以上ある文字数グループだけ取得
    2. カテゴリごとの平均文字数で絞り込み
  8. バイト数と文字数の違い
    1. エンコーディングによるバイト数の違い
    2. RDBMS別のバイト数取得関数
    3. Oracle の LENGTHB
  9. TRIM との組み合わせ
    1. TRIM + CHAR_LENGTH で正確な文字数を取得
    2. 全角スペースも除去する(MySQL)
  10. NULL・空文字列の扱い
    1. NULL の場合
    2. COALESCE / IFNULL で NULL を安全に処理
    3. NULL を除外してソートする
  11. RDBMS間の比較(MySQL / PostgreSQL / SQL Server / Oracle)
    1. 文字数・バイト数取得関数の比較
    2. 各RDBMSでの文字数ソート構文
  12. よくあるエラーと対処法
    1. エラー1: LENGTH と CHAR_LENGTH の混同
    2. エラー2: WHERE句でエイリアスを使った場合
    3. エラー3: RDBMS の関数名を間違えた場合
  13. 実務で使えるパターン集
    1. パターン1: データクレンジング(異常データの検出)
    2. パターン2: バリデーション(入力値の検証)
    3. パターン3: 文字数の統計情報
    4. パターン4: VARCHAR カラムの使用率分析
    5. パターン5: 文字数でデータを切り捨て(トランケーション検出)
  14. まとめ
  15. 関連記事

サンプルテーブル

この記事では、以下の products テーブルを使って解説します。

id product_name category description
1 ノートPC 電子機器 軽量で持ち運びに便利なノートパソコン
2 ワイヤレスマウス 周辺機器 Bluetooth対応の静音マウス
3 USBケーブル アクセサリ Type-C対応
4 キーボード 周辺機器 メカニカル式のゲーミングキーボード。Cherry MXスイッチ搭載
5 モニター 電子機器 27インチ4K対応ディスプレイ
6 SDカード アクセサリ NULL
7 マウスパッド アクセサリ (空文字列)

注意:id=6 の description は NULL、id=7 は空文字列(”)です。NULL と空文字列の違いは後述のセクションで詳しく解説します。

LENGTH / CHAR_LENGTH で文字数をカウントする基本

CHAR_LENGTH(文字数を取得)

CHAR_LENGTH()(または CHARACTER_LENGTH())は、文字列の文字数を返します。マルチバイト文字(日本語など)も1文字として正しくカウントします。

CHAR_LENGTH の基本構文
SELECT
  product_name,
  CHAR_LENGTH(product_name) AS char_count
FROM products;

実行結果

+-----------------------+------------+
| product_name          | char_count |
+-----------------------+------------+
| ノートPC              |          4 |
| ワイヤレスマウス      |          8 |
| USBケーブル           |          6 |
| キーボード            |          5 |
| モニター              |          4 |
| SDカード              |          4 |
| マウスパッド          |          6 |
+-----------------------+------------+

LENGTH(バイト数を取得)

MySQL では LENGTH() は文字列のバイト数を返します。UTF-8 では日本語1文字が3バイトになるため、CHAR_LENGTH() と結果が異なります。

LENGTH(バイト数)と CHAR_LENGTH(文字数)の比較
SELECT
  product_name,
  LENGTH(product_name)      AS byte_count,
  CHAR_LENGTH(product_name) AS char_count
FROM products;

実行結果

+-----------------------+------------+------------+
| product_name          | byte_count | char_count |
+-----------------------+------------+------------+
| ノートPC              |         10 |          4 |
| ワイヤレスマウス      |         24 |          8 |
| USBケーブル           |         12 |          6 |
| キーボード            |         15 |          5 |
| モニター              |         12 |          4 |
| SDカード              |          9 |          4 |
| マウスパッド          |         15 |          6 |
+-----------------------+------------+------------+

ポイント:日本語の文字数をカウントしたい場合は CHAR_LENGTH() を使いましょう。LENGTH() はバイト数を返すため、マルチバイト文字では文字数と一致しません。

LEN(SQL Server)との違い

SQL Server では CHAR_LENGTH() の代わりに LEN() を使います。ただし、末尾のスペースを除外してカウントする点に注意が必要です。

SQL Server – LEN の動作
-- SQL Server
SELECT
  LEN('ABC')     AS len_result,     -- 結果: 3
  LEN('ABC   ')  AS len_trailing,   -- 結果: 3(末尾スペース除外)
  LEN('   ABC')  AS len_leading;    -- 結果: 6(先頭スペースは含む)

末尾スペースを含めてカウントしたい場合は DATALENGTH() を使い、バイト数を文字数に変換します。

SQL Server – 末尾スペースを含めてカウント
-- NVARCHAR の場合(1文字 = 2バイト)
SELECT
  DATALENGTH(N'ABC   ') / 2 AS total_len;  -- 結果: 6

-- VARCHAR の場合(1文字 = 1バイト)
SELECT
  DATALENGTH('ABC   ') AS total_len;      -- 結果: 6

注意:LEN() は末尾のスペースを自動的に除外します。スペースを含む正確な文字数が必要な場合は DATALENGTH() を使いましょう。

文字数の多い順・少ない順でソートする

文字数の多い順(降順 / DESC)

文字数が多い順にソートするには、ORDER BYCHAR_LENGTH()DESC を指定します。

文字数の多い順でソート
SELECT
  product_name,
  CHAR_LENGTH(product_name) AS char_count
FROM products
ORDER BY CHAR_LENGTH(product_name) DESC;

実行結果

+-----------------------+------------+
| product_name          | char_count |
+-----------------------+------------+
| ワイヤレスマウス      |          8 |
| USBケーブル           |          6 |
| マウスパッド          |          6 |
| キーボード            |          5 |
| ノートPC              |          4 |
| モニター              |          4 |
| SDカード              |          4 |
+-----------------------+------------+

文字数の少ない順(昇順 / ASC)

文字数が少ない順にソートするには、ASC を指定します(省略しても昇順になります)。

文字数の少ない順でソート
SELECT
  product_name,
  CHAR_LENGTH(product_name) AS char_count
FROM products
ORDER BY CHAR_LENGTH(product_name) ASC;

実行結果

+-----------------------+------------+
| product_name          | char_count |
+-----------------------+------------+
| ノートPC              |          4 |
| モニター              |          4 |
| SDカード              |          4 |
| キーボード            |          5 |
| USBケーブル           |          6 |
| マウスパッド          |          6 |
| ワイヤレスマウス      |          8 |
+-----------------------+------------+

エイリアスを使ったソート

ORDER BY ではエイリアス名を使うこともできます。同じ関数を繰り返し書く必要がなくなり、可読性が向上します。

エイリアスを使ったソート
SELECT
  product_name,
  CHAR_LENGTH(product_name) AS char_count
FROM products
ORDER BY char_count DESC;

ポイント:MySQL・PostgreSQL では ORDER BY でエイリアスが使えます。ただし SQL Server では ORDER BY でのみ使用可能で、WHERE ではエイリアスを使えません。

WHERE句で文字数をフィルタリングする

WHERE 句で CHAR_LENGTH() を使うと、特定の文字数の条件に合うデータだけを抽出できます。

文字数が指定値以上のデータを取得

5文字以上の商品名を取得
SELECT
  product_name,
  CHAR_LENGTH(product_name) AS char_count
FROM products
WHERE CHAR_LENGTH(product_name) >= 5
ORDER BY char_count DESC;

実行結果

+-----------------------+------------+
| product_name          | char_count |
+-----------------------+------------+
| ワイヤレスマウス      |          8 |
| USBケーブル           |          6 |
| マウスパッド          |          6 |
| キーボード            |          5 |
+-----------------------+------------+

文字数の範囲を指定(BETWEEN)

文字数が4〜6文字のデータを取得
SELECT
  product_name,
  CHAR_LENGTH(product_name) AS char_count
FROM products
WHERE CHAR_LENGTH(product_name) BETWEEN 4 AND 6
ORDER BY char_count;

実行結果

+-----------------------+------------+
| product_name          | char_count |
+-----------------------+------------+
| ノートPC              |          4 |
| モニター              |          4 |
| SDカード              |          4 |
| キーボード            |          5 |
| USBケーブル           |          6 |
| マウスパッド          |          6 |
+-----------------------+------------+

description の文字数でフィルタリング

説明文が10文字以上のデータを取得
SELECT
  product_name,
  description,
  CHAR_LENGTH(description) AS desc_len
FROM products
WHERE CHAR_LENGTH(description) >= 10
ORDER BY desc_len DESC;

実行結果

+--------------------+---------------------------------------------+----------+
| product_name       | description                                 | desc_len |
+--------------------+---------------------------------------------+----------+
| キーボード         | メカニカル式のゲーミングキーボード。Cherry... |       28 |
| ノートPC           | 軽量で持ち運びに便利なノートパソコン         |       17 |
| モニター           | 27インチ4K対応ディスプレイ                   |       14 |
| ワイヤレスマウス   | Bluetooth対応の静音マウス                    |       14 |
+--------------------+---------------------------------------------+----------+

GROUP BY + CHAR_LENGTH で文字数別に集計する

GROUP BYCHAR_LENGTH() を組み合わせると、文字数別にデータを集計できます。

商品名の文字数ごとの件数

文字数ごとの件数を集計
SELECT
  CHAR_LENGTH(product_name) AS char_count,
  COUNT(*) AS product_count
FROM products
GROUP BY CHAR_LENGTH(product_name)
ORDER BY char_count;

実行結果

+------------+---------------+
| char_count | product_count |
+------------+---------------+
|          4 |             3 |
|          5 |             1 |
|          6 |             2 |
|          8 |             1 |
+------------+---------------+

文字数の範囲別に集計(CASE式)

文字数を範囲ごとにグループ化して集計することもできます。

文字数の範囲別集計
SELECT
  CASE
    WHEN CHAR_LENGTH(product_name) <= 4  THEN '1〜4文字'
    WHEN CHAR_LENGTH(product_name) <= 6  THEN '5〜6文字'
    ELSE '7文字以上'
  END AS length_range,
  COUNT(*) AS cnt
FROM products
GROUP BY length_range
ORDER BY MIN(CHAR_LENGTH(product_name));

実行結果

+--------------+-----+
| length_range | cnt |
+--------------+-----+
| 1〜4文字     |   3 |
| 5〜6文字     |   3 |
| 7文字以上    |   1 |
+--------------+-----+

HAVING で文字数の集計結果をフィルタリング

HAVING を使うと、GROUP BY で集計した後の結果に対して条件を付けられます。

2件以上ある文字数グループだけ取得

HAVING で集計後のフィルタリング
SELECT
  CHAR_LENGTH(product_name) AS char_count,
  COUNT(*) AS product_count
FROM products
GROUP BY CHAR_LENGTH(product_name)
HAVING COUNT(*) >= 2
ORDER BY char_count;

実行結果

+------------+---------------+
| char_count | product_count |
+------------+---------------+
|          4 |             3 |
|          6 |             2 |
+------------+---------------+

カテゴリごとの平均文字数で絞り込み

平均文字数が5以上のカテゴリを取得
SELECT
  category,
  AVG(CHAR_LENGTH(product_name)) AS avg_len,
  MAX(CHAR_LENGTH(product_name)) AS max_len,
  MIN(CHAR_LENGTH(product_name)) AS min_len
FROM products
GROUP BY category
HAVING AVG(CHAR_LENGTH(product_name)) >= 5
ORDER BY avg_len DESC;

実行結果

+----------+---------+---------+---------+
| category | avg_len | max_len | min_len |
+----------+---------+---------+---------+
| 周辺機器 |  6.5000 |       8 |       5 |
| アクセサリ |  5.3333 |       6 |       4 |
+----------+---------+---------+---------+

バイト数と文字数の違い

文字数を扱う際に最も注意が必要なのが、バイト数と文字数の違いです。特に日本語などのマルチバイト文字を扱う場合、関数の選択を間違えると意図しない結果になります。

エンコーディングによるバイト数の違い

文字 UTF-8 Shift_JIS 文字数
A(半角英字) 1バイト 1バイト 1文字
あ(ひらがな) 3バイト 2バイト 1文字
漢(漢字) 3バイト 2バイト 1文字
?(絵文字) 4バイト 非対応 1文字

RDBMS別のバイト数取得関数

RDBMS バイト数 文字数
MySQL LENGTH() CHAR_LENGTH()
PostgreSQL OCTET_LENGTH() LENGTH() / CHAR_LENGTH()
SQL Server DATALENGTH() LEN()
Oracle LENGTHB() LENGTH()

注意:MySQL の LENGTH() と PostgreSQL の LENGTH() は動作が異なります。MySQL の LENGTH() はバイト数、PostgreSQL の LENGTH() は文字数を返します。RDBMS を移行する際は十分注意してください。

Oracle の LENGTHB

Oracle – LENGTH と LENGTHB の比較
-- Oracle
SELECT
  LENGTH('こんにちは')   AS char_len,  -- 結果: 5(文字数)
  LENGTHB('こんにちは')  AS byte_len   -- 結果: 15(UTF-8の場合)
FROM DUAL;

TRIM との組み合わせ

文字数をカウントする際、前後のスペースが結果に影響することがあります。TRIM() と組み合わせて正確な文字数を取得しましょう。

TRIM + CHAR_LENGTH で正確な文字数を取得

スペースを除去してからカウント
SELECT
  product_name,
  CHAR_LENGTH(product_name)         AS with_space,
  CHAR_LENGTH(TRIM(product_name))   AS trimmed
FROM products;

各 RDBMS のトリム関数の違いも確認しておきましょう。

処理 MySQL / PostgreSQL SQL Server Oracle
両端除去 TRIM(col) TRIM(col) TRIM(col)
先頭除去 LTRIM(col) LTRIM(col) LTRIM(col)
末尾除去 RTRIM(col) RTRIM(col) RTRIM(col)

全角スペースも除去する(MySQL)

MySQL の TRIM() は半角スペースのみ除去します。全角スペースも除去したい場合は REPLACE() と組み合わせます。

全角スペースも除去してカウント
SELECT
  CHAR_LENGTH(
    TRIM(REPLACE(product_name, ' ', ''))
  ) AS clean_len
FROM products;

NULL・空文字列の扱い

文字数をカウントする際、NULL空文字列(”)では動作が異なります。正しく処理しないとエラーや意図しない結果の原因になります。

NULL の場合

NULL に対する CHAR_LENGTH の動作
SELECT
  product_name,
  description,
  CHAR_LENGTH(description) AS desc_len
FROM products
WHERE id IN (6, 7);

実行結果

+----------------+-------------+----------+
| product_name   | description | desc_len |
+----------------+-------------+----------+
| SDカード       | NULL        |     NULL |
| マウスパッド   |             |        0 |
+----------------+-------------+----------+

NULL と空文字列の違い

  • NULL: 値が存在しない状態。CHAR_LENGTH(NULL)NULL を返す
  • 空文字列(”): 長さ0の文字列。CHAR_LENGTH('')0 を返す
  • Oracle では空文字列は NULL として扱われる点に注意

COALESCE / IFNULL で NULL を安全に処理

NULL を 0 として扱う
-- 方法1: COALESCE(すべてのRDBMSで使用可能)
SELECT
  product_name,
  COALESCE(CHAR_LENGTH(description), 0) AS desc_len
FROM products;

-- 方法2: IFNULL(MySQL専用)
SELECT
  product_name,
  IFNULL(CHAR_LENGTH(description), 0) AS desc_len
FROM products;

実行結果

+-----------------------+----------+
| product_name          | desc_len |
+-----------------------+----------+
| ノートPC              |       17 |
| ワイヤレスマウス      |       14 |
| USBケーブル           |        5 |
| キーボード            |       28 |
| モニター              |       14 |
| SDカード              |        0 |
| マウスパッド          |        0 |
+-----------------------+----------+

NULL を除外してソートする

NULL を除外して文字数順にソート
SELECT
  product_name,
  description,
  CHAR_LENGTH(description) AS desc_len
FROM products
WHERE description IS NOT NULL
  AND description != ''
ORDER BY desc_len DESC;

RDBMS間の比較(MySQL / PostgreSQL / SQL Server / Oracle)

文字数関連の関数は RDBMS ごとに名前や動作が異なります。以下のテーブルで一覧比較できます。

文字数・バイト数取得関数の比較

用途 MySQL PostgreSQL SQL Server Oracle
文字数 CHAR_LENGTH() LENGTH()
CHAR_LENGTH()
LEN() LENGTH()
バイト数 LENGTH() OCTET_LENGTH() DATALENGTH() LENGTHB()
末尾スペース 含む 含む 除外(LEN) 含む
NULLの結果 NULL NULL NULL NULL
空文字列 0 0 0 NULL(※)

注意:Oracle では空文字列(”)は NULL として扱われます。そのため LENGTH('')0 ではなく NULL を返します。

各RDBMSでの文字数ソート構文

MySQL
SELECT col, CHAR_LENGTH(col) AS len
FROM table_name
ORDER BY CHAR_LENGTH(col) DESC;
PostgreSQL
SELECT col, LENGTH(col) AS len
FROM table_name
ORDER BY LENGTH(col) DESC;
SQL Server
SELECT col, LEN(col) AS len
FROM table_name
ORDER BY LEN(col) DESC;
Oracle
SELECT col, LENGTH(col) AS len
FROM table_name
ORDER BY LENGTH(col) DESC;

よくあるエラーと対処法

エラー1: LENGTH と CHAR_LENGTH の混同

問題 原因 対処法
日本語の文字数が多くカウントされる MySQL で LENGTH() を使っている(バイト数を返す) CHAR_LENGTH() に変更する
末尾スペースがカウントされない SQL Server の LEN() は末尾スペースを除外する DATALENGTH() を使う
空文字列で NULL が返る Oracle は空文字列を NULL として扱う NVL(LENGTH(col), 0) を使う

エラー2: WHERE句でエイリアスを使った場合

NGパターン
-- エラーになる(WHERE句ではエイリアスが使えない)
SELECT
  product_name,
  CHAR_LENGTH(product_name) AS char_count
FROM products
WHERE char_count >= 5;  -- Unknown column 'char_count'
OKパターン
-- 正しい: WHERE句では関数を直接使う
SELECT
  product_name,
  CHAR_LENGTH(product_name) AS char_count
FROM products
WHERE CHAR_LENGTH(product_name) >= 5;

ポイント:SQL の処理順序は FROMWHEREGROUP BYHAVINGSELECTORDER BY です。WHERESELECT より前に実行されるため、エイリアスが使えません。ORDER BYSELECT の後に実行されるため、エイリアスが使えます。

エラー3: RDBMS の関数名を間違えた場合

エラー内容 原因 対処法
FUNCTION LEN does not exist MySQL で SQL Server の LEN() を使った CHAR_LENGTH() に変更
FUNCTION CHAR_LENGTH does not exist SQL Server で CHAR_LENGTH() を使った LEN() に変更
FUNCTION LENGTHB does not exist MySQL で Oracle の LENGTHB() を使った LENGTH() に変更

実務で使えるパターン集

パターン1: データクレンジング(異常データの検出)

文字数をチェックして、入力ミスや異常なデータを検出します。

電話番号の文字数チェック
-- 電話番号が10〜11桁でないデータを検出
SELECT
  id,
  phone_number,
  CHAR_LENGTH(REPLACE(phone_number, '-', '')) AS digit_count
FROM customers
WHERE CHAR_LENGTH(REPLACE(phone_number, '-', ''))
      NOT BETWEEN 10 AND 11;

パターン2: バリデーション(入力値の検証)

パスワードのバリデーション
-- パスワードが8文字未満のユーザーを検出
SELECT
  user_name,
  CHAR_LENGTH(password_hash) AS pass_len
FROM users
WHERE CHAR_LENGTH(password_hash) < 8;

パターン3: 文字数の統計情報

テーブル内の文字数統計
SELECT
  MIN(CHAR_LENGTH(product_name))  AS min_len,
  MAX(CHAR_LENGTH(product_name))  AS max_len,
  AVG(CHAR_LENGTH(product_name))  AS avg_len,
  COUNT(*) AS total_count
FROM products;

実行結果

+---------+---------+---------+-------------+
| min_len | max_len | avg_len | total_count |
+---------+---------+---------+-------------+
|       4 |       8 |  5.2857 |           7 |
+---------+---------+---------+-------------+

パターン4: VARCHAR カラムの使用率分析

カラムの最大長と実際の使用率を分析
-- product_name が VARCHAR(100) の場合
SELECT
  MAX(CHAR_LENGTH(product_name))        AS max_used,
  ROUND(
    MAX(CHAR_LENGTH(product_name)) / 100.0 * 100, 1
  ) AS usage_pct
FROM products;

ポイント:VARCHAR のサイズが大きすぎる場合、実際に使われている最大文字数を確認して適切なサイズに変更することで、ストレージの最適化やインデックスの効率化が可能です。

パターン5: 文字数でデータを切り捨て(トランケーション検出)

移行先のカラムに収まらないデータを事前検出
-- 移行先が VARCHAR(20) の場合、超過するデータを検出
SELECT
  id,
  description,
  CHAR_LENGTH(description) AS current_len
FROM products
WHERE CHAR_LENGTH(description) > 20;

まとめ

この記事のポイント

  • CHAR_LENGTH(): 文字数を取得(MySQL)。日本語も正しくカウント
  • LENGTH(): MySQL ではバイト数、PostgreSQL/Oracle では文字数を返す
  • LEN(): SQL Server 用。末尾スペースを除外する
  • ORDER BY CHAR_LENGTH(col) DESC/ASC: 文字数で多い順・少ない順にソート
  • WHERE CHAR_LENGTH(col) >= N: 文字数でフィルタリング
  • GROUP BY + HAVING: 文字数別に集計・フィルタリング
  • COALESCE() で NULL を安全に処理する
  • TRIM() と組み合わせてスペースを除去した文字数を取得
  • RDBMS ごとに関数名・動作が異なるため、必ず対応表を確認する

関連記事