问题
I want to group by t0.method
in strict string comparation, i.e. "GET ", "GET" and "get" in different group, so a BINARY
is added in front of the t0.method
field which appears in the group by sentence. but I can't add a BINARY
to this field which appears in the select sentence, since this will cause an encoding problem when non-ascii characters appears in the data.
So following is the SQL query I finally get:
SELECT `t0`.`method` AS `d0`,
SUM(`t0`.`success`) AS `m0`
FROM `invoke_statistics` AS `t0`
GROUP BY BINARY `t0`.`method`
LIMIT 20000
But unfortunately, I got the following error message then..
Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 't0.method' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
So, what is the correct way to do all this without causing any encoding problem or incompatibility problem with the "sql_mode=only_full_group_by" things?
NOTE:
- I'm not able to modify the sql_mode option.
- I'm not able to make sure that there is no non-ascii characters appears in the data
- I'm not able to know what char set is used before generate a query. so the
collate utf8_bin
or similar things is not able to work since it may cause some errors likeCOLLATION 'UTF8_BIN' is not valid for CHARACTER SET 'latin1'
I'm doing something about code generation, so the other's answer which depends on a lot of assumptions can't solve my problem, I need some general solution
回答1:
Both of the following work when the SQL mode includes ONLY_FULL_GROUP_BY:
Make your grouping column part of the select-list:
SELECT BINARY `t0`.`method` AS `d0`,
SUM(`t0`.`success`) AS `m0`
FROM `invoke_statistics` AS `t0`
GROUP BY BINARY `t0`.`method`
LIMIT 20000
Or make your select-list use an aggregate function:
SELECT MAX(`t0`.`method`) AS `d0`,
SUM(`t0`.`success`) AS `m0`
FROM `invoke_statistics` AS `t0`
GROUP BY BINARY `t0`.`method`
LIMIT 20000
I tested both of these queries on MySQL 8.0 DMR.
回答2:
(There seem to be two questions rolled into one. This addresses the collation problem.)
Plan A
The "right" answer is to change the collation in the table definition:
CREATE TABLE ...
method ... COLLATE xxx_bin
...
Where xxx is the charset involved. That is (apparently), latin1_bin
. ("Latin1_General_CS_AS" comes from some other vendor, not MySQL.)
Caveat: This will affect all other comparisons (WHERE
, ORDER BY
, =
) involving the column method
. (This may or may not be an issue.)
Plan B
The way to do it in the query is
... GROUP BY method COLLATE latin1_bin ...
A COLLATE
clause can be tacked onto a variety of things, including comparisons and ORDER BY
. But, note, it prevents the use of an index for optimization.
来源:https://stackoverflow.com/questions/40396426/how-to-group-by-in-strict-string-comparation-when-sql-mode-only-full-group-by