【MySQL】ANY_VALUE関数でGROUP BYを使う時でも自由にSELECTを書く

  • 2025年8月7日
  • SQL

 MySQLには ONLY_FULL_GROUP_BY というモードがあります。これは GROUP BY に含まれおらず複数の値を取る可能性がある列を SELECT や ORDER BY に含めるとエラーになる機能です。これが有効になると異なる値を持つ可能性がある列の値をどれかひとつだけ持ってくるということがなくなり、あいまいな結果が排除されます。これは予期せぬ結果を防ぐという観点で役に立ってくれる機能です。
 ONLY_FULL_GROUP_BYモードでのエラーを回避する方法として事細かに集計関数を使ったり、サブクエリを駆使して問題のない形に整形する方法がありますが、どちらも速度面で遅くなりやすいです。本当にその指定が必要であれば指定をした上でクエリを工夫したり、データベースをリファクタリングしたり、アプリケーション上のデータ取得ロジックを変えたりして高速化すべきですが、そうでない時もあります。もしONLY_FULL_GROUP_BYでエラーになっている部分がGROUP BYしたカラムらの値に対して一意に定まる値を持つカラムであったり、本当に存在する値のどれかを取って来るだけでいい場合はANY_VALUE関数を用いてパフォーマンスを落とさずにGROUP BYした結果を得ることができます。

 ANY_VALUE関数のリファレンスは次リンクです。

MySQL :: MySQL 8.0 リファレンスマニュアル :: 12.24 その他の関数#function_any-value

 ANY_VALUE関数はたとえば次のように使えます

SELECT
    user_id,
    ANY_VALUE(user_name) AS user_name,
    COUNT(*) AS cnt
FROM
    access_log
GROUP BY
    user_id;

 ユーザーごとにアクセスを数えて、一緒に記録してある当時の名前をANY_VALUEで1つ持ってくるクエリです。このクエリは誰がどれだけアクセスしたか見るためのクエリであり、ユーザーID単位で厳密に集計する必要があるけどユーザーIDに対応する名前は誰の事かなんとなく分かればいいクエリです。

 このようにANY_VALUE関数を使うと ONLY_FULL_GROUP_BY モードが有効になっている MySQL 環境でも柔軟に GROUP BY を使ったクエリが書けるようになります。何らかの理由で「この列はグループ単位で意味のある値を一つ取得できればよい」と判断できる状況なら、ANY_VALUE はいい選択肢です。

 とはいえ使用にあたっては注意も必要です。ANY_VALUEは本当にどれか一つを無作為に返すため、複数の値が混在していて全ての値んいついて考慮すべきカラムに対して用いると期待通りの結果にならない可能性が高いです。常に最新のデータを取得したい、全てのデータを結合して見たい、といった場合には、ANY_VALUEは 避けMAX や GROUP_CONCAT のような集約関数を使ったり、サブクエリを使ったりする別のアプローチをとるべきです。

>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG