宣言
ANY_VALUE(arg)
説明
sql_mode が ONLY_FULL_GROUP_BY SQLモードを有効にすると、この関数は FULL GROUP BY 以外の操作を実行し、ONLY_FULL_GROUP_BY 値が拒否されるのを抑制します。
ANY_VALUE() は、同一グループに割り当てられたデータの最初のデータの指定された列値を返します。関数の戻り値と型は、その引数の戻り値と型と同じです。
以下の例では、name が非インデックス列であり、ONLY_FULL_GROUP_BY SQL モードが有効な場合、GROUP BY クエリは失敗します。これは、city が集約されていない列であるため、各 name グループ内の city 値が不確定であるためです。
obclient> CREATE TABLE tbl1(name VARCHAR(20),age VARCHAR(10),city VARCHAR(50));
obclient> INSERT INTO tbl1 VALUES ('Alex',20,'BeiJing'),('Jim',25,'HangZhou'),('Blair',35,'NanJing');
obclient> SET sql_mode='ONLY_FULL_GROUP_BY';
Query OK, 0 rows affected
obclient> SELECT name, city, MAX(age) FROM tbl1 GROUP BY name;
ERROR 1055 (42000): 'test.tbl1.city' is not in GROUP BY
一つの解決策は、テーブルを変更して name を主キーまたは一意の NOT NULL 列にすることで、city を name によって一意に特定できるようにすることです(ただし、有効な name 値として NULL を許可しなければならない場合は、この方法は適用されません)。
もう一つの解決策は、ANY_VALUE() を使用して city を参照することで、各 name グループ内の city 値の不確実性を無視してクエリを受け入れることです。ANY_VALUE() は集約関数ではなく、不確定なテストを抑制する役割しか果たしません。
obclient> SELECT name, ANY_VALUE(city), MAX(age) FROM tbl1 GROUP BY name;
+-------+-----------------+----------+
| name | ANY_VALUE(city) | MAX(age) |
+-------+-----------------+----------+
| Alex | BeiJing | 20 |
| Jim | HangZhou | 25 |
| Blair | NanJing | 35 |
+-------+-----------------+----------+
3 rows in set
もう一つの方法は、ONLY_FULL_GROUP_BY を無効にすることです。これは、上述のように、ONLY_FULL_GROUP_BY を有効にした状態で ANY_VALUE() を使用することと同じです。
例
GROUP BY 句がない場合、単一のグループの場合にどの name 値を選択するかが不確定であるため、クエリは失敗します。しかし、ANY_VALUE() はこの問題を回避し、データベースが集約関数を参照するクエリを受け入れるようにします。
obclient> SELECT name, MAX(age) FROM tbl1;
ERROR 1140 (42000): Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause
obclient> SELECT ANY_VALUE(name), MAX(age) FROM tbl1;
+-----------------+----------+
| ANY_VALUE(name) | MAX(age) |
+-----------------+----------+
| Alex | 35 |
+-----------------+----------+
1 row in set