データベースに格納された文字列の文字数をカウントし、その結果を多い順(降順)や少ない順(昇順)でソートすることは、データ分析やデータクレンジングで頻繁に使うテクニックです。
この記事では、LENGTH・CHAR_LENGTH・LENなど文字数を取得する関数の使い方から、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間比較
- よくあるエラーと対処法
- 実務パターン(データクレンジング、バリデーション等)
サンプルテーブル
この記事では、以下の products テーブルを使って解説します。
注意:id=6 の description は NULL、id=7 は空文字列(”)です。NULL と空文字列の違いは後述のセクションで詳しく解説します。
LENGTH / CHAR_LENGTH で文字数をカウントする基本
CHAR_LENGTH(文字数を取得)
CHAR_LENGTH()(または CHARACTER_LENGTH())は、文字列の文字数を返します。マルチバイト文字(日本語など)も1文字として正しくカウントします。
実行結果
+-----------------------+------------+ | product_name | char_count | +-----------------------+------------+ | ノートPC | 4 | | ワイヤレスマウス | 8 | | USBケーブル | 6 | | キーボード | 5 | | モニター | 4 | | SDカード | 4 | | マウスパッド | 6 | +-----------------------+------------+
LENGTH(バイト数を取得)
MySQL では LENGTH() は文字列のバイト数を返します。UTF-8 では日本語1文字が3バイトになるため、CHAR_LENGTH() と結果が異なります。
実行結果
+-----------------------+------------+------------+ | 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() を使います。ただし、末尾のスペースを除外してカウントする点に注意が必要です。
末尾スペースを含めてカウントしたい場合は DATALENGTH() を使い、バイト数を文字数に変換します。
注意:LEN() は末尾のスペースを自動的に除外します。スペースを含む正確な文字数が必要な場合は DATALENGTH() を使いましょう。
文字数の多い順・少ない順でソートする
文字数の多い順(降順 / DESC)
文字数が多い順にソートするには、ORDER BY に CHAR_LENGTH() と DESC を指定します。
実行結果
+-----------------------+------------+ | product_name | char_count | +-----------------------+------------+ | ワイヤレスマウス | 8 | | USBケーブル | 6 | | マウスパッド | 6 | | キーボード | 5 | | ノートPC | 4 | | モニター | 4 | | SDカード | 4 | +-----------------------+------------+
文字数の少ない順(昇順 / ASC)
文字数が少ない順にソートするには、ASC を指定します(省略しても昇順になります)。
実行結果
+-----------------------+------------+ | product_name | char_count | +-----------------------+------------+ | ノートPC | 4 | | モニター | 4 | | SDカード | 4 | | キーボード | 5 | | USBケーブル | 6 | | マウスパッド | 6 | | ワイヤレスマウス | 8 | +-----------------------+------------+
エイリアスを使ったソート
ORDER BY ではエイリアス名を使うこともできます。同じ関数を繰り返し書く必要がなくなり、可読性が向上します。
ポイント:MySQL・PostgreSQL では ORDER BY でエイリアスが使えます。ただし SQL Server では ORDER BY でのみ使用可能で、WHERE ではエイリアスを使えません。
WHERE句で文字数をフィルタリングする
WHERE 句で CHAR_LENGTH() を使うと、特定の文字数の条件に合うデータだけを抽出できます。
文字数が指定値以上のデータを取得
実行結果
+-----------------------+------------+ | product_name | char_count | +-----------------------+------------+ | ワイヤレスマウス | 8 | | USBケーブル | 6 | | マウスパッド | 6 | | キーボード | 5 | +-----------------------+------------+
文字数の範囲を指定(BETWEEN)
実行結果
+-----------------------+------------+ | product_name | char_count | +-----------------------+------------+ | ノートPC | 4 | | モニター | 4 | | SDカード | 4 | | キーボード | 5 | | USBケーブル | 6 | | マウスパッド | 6 | +-----------------------+------------+
description の文字数でフィルタリング
実行結果
+--------------------+---------------------------------------------+----------+ | product_name | description | desc_len | +--------------------+---------------------------------------------+----------+ | キーボード | メカニカル式のゲーミングキーボード。Cherry... | 28 | | ノートPC | 軽量で持ち運びに便利なノートパソコン | 17 | | モニター | 27インチ4K対応ディスプレイ | 14 | | ワイヤレスマウス | Bluetooth対応の静音マウス | 14 | +--------------------+---------------------------------------------+----------+
GROUP BY + CHAR_LENGTH で文字数別に集計する
GROUP BY と CHAR_LENGTH() を組み合わせると、文字数別にデータを集計できます。
商品名の文字数ごとの件数
実行結果
+------------+---------------+ | char_count | product_count | +------------+---------------+ | 4 | 3 | | 5 | 1 | | 6 | 2 | | 8 | 1 | +------------+---------------+
文字数の範囲別に集計(CASE式)
文字数を範囲ごとにグループ化して集計することもできます。
実行結果
+--------------+-----+ | length_range | cnt | +--------------+-----+ | 1〜4文字 | 3 | | 5〜6文字 | 3 | | 7文字以上 | 1 | +--------------+-----+
HAVING で文字数の集計結果をフィルタリング
HAVING を使うと、GROUP BY で集計した後の結果に対して条件を付けられます。
2件以上ある文字数グループだけ取得
実行結果
+------------+---------------+ | char_count | product_count | +------------+---------------+ | 4 | 3 | | 6 | 2 | +------------+---------------+
カテゴリごとの平均文字数で絞り込み
実行結果
+----------+---------+---------+---------+ | category | avg_len | max_len | min_len | +----------+---------+---------+---------+ | 周辺機器 | 6.5000 | 8 | 5 | | アクセサリ | 5.3333 | 6 | 4 | +----------+---------+---------+---------+
バイト数と文字数の違い
文字数を扱う際に最も注意が必要なのが、バイト数と文字数の違いです。特に日本語などのマルチバイト文字を扱う場合、関数の選択を間違えると意図しない結果になります。
エンコーディングによるバイト数の違い
RDBMS別のバイト数取得関数
注意:MySQL の LENGTH() と PostgreSQL の LENGTH() は動作が異なります。MySQL の LENGTH() はバイト数、PostgreSQL の LENGTH() は文字数を返します。RDBMS を移行する際は十分注意してください。
Oracle の LENGTHB
TRIM との組み合わせ
文字数をカウントする際、前後のスペースが結果に影響することがあります。TRIM() と組み合わせて正確な文字数を取得しましょう。
TRIM + CHAR_LENGTH で正確な文字数を取得
各 RDBMS のトリム関数の違いも確認しておきましょう。
全角スペースも除去する(MySQL)
MySQL の TRIM() は半角スペースのみ除去します。全角スペースも除去したい場合は REPLACE() と組み合わせます。
NULL・空文字列の扱い
文字数をカウントする際、NULL と空文字列(”)では動作が異なります。正しく処理しないとエラーや意図しない結果の原因になります。
NULL の場合
実行結果
+----------------+-------------+----------+ | product_name | description | desc_len | +----------------+-------------+----------+ | SDカード | NULL | NULL | | マウスパッド | | 0 | +----------------+-------------+----------+
NULL と空文字列の違い
- NULL: 値が存在しない状態。
CHAR_LENGTH(NULL)は NULL を返す - 空文字列(”): 長さ0の文字列。
CHAR_LENGTH('')は 0 を返す - Oracle では空文字列は NULL として扱われる点に注意
COALESCE / IFNULL で NULL を安全に処理
実行結果
+-----------------------+----------+ | product_name | desc_len | +-----------------------+----------+ | ノートPC | 17 | | ワイヤレスマウス | 14 | | USBケーブル | 5 | | キーボード | 28 | | モニター | 14 | | SDカード | 0 | | マウスパッド | 0 | +-----------------------+----------+
NULL を除外してソートする
RDBMS間の比較(MySQL / PostgreSQL / SQL Server / Oracle)
文字数関連の関数は RDBMS ごとに名前や動作が異なります。以下のテーブルで一覧比較できます。
文字数・バイト数取得関数の比較
注意:Oracle では空文字列(”)は NULL として扱われます。そのため LENGTH('') は 0 ではなく NULL を返します。
各RDBMSでの文字数ソート構文
よくあるエラーと対処法
エラー1: LENGTH と CHAR_LENGTH の混同
エラー2: WHERE句でエイリアスを使った場合
ポイント:SQL の処理順序は FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY です。WHERE は SELECT より前に実行されるため、エイリアスが使えません。ORDER BY は SELECT の後に実行されるため、エイリアスが使えます。
エラー3: RDBMS の関数名を間違えた場合
実務で使えるパターン集
パターン1: データクレンジング(異常データの検出)
文字数をチェックして、入力ミスや異常なデータを検出します。
パターン2: バリデーション(入力値の検証)
パターン3: 文字数の統計情報
実行結果
+---------+---------+---------+-------------+ | min_len | max_len | avg_len | total_count | +---------+---------+---------+-------------+ | 4 | 8 | 5.2857 | 7 | +---------+---------+---------+-------------+
パターン4: VARCHAR カラムの使用率分析
ポイント:VARCHAR のサイズが大きすぎる場合、実際に使われている最大文字数を確認して適切なサイズに変更することで、ストレージの最適化やインデックスの効率化が可能です。
パターン5: 文字数でデータを切り捨て(トランケーション検出)
まとめ
この記事のポイント
- 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 ごとに関数名・動作が異なるため、必ず対応表を確認する