MySQL aggregate functions (c) treatment of a GROUP BY MySQL

  MySQL 5.7 from the original Official Handbook: 12.20.3 Handling of the GROUP BY MySQL

 

  SQL-92 and earlier versions do not allow SELECT list, HAVING condition or ORDER BY query that references a list of non-polymeric columns are not named in the GROUP BY clause. That is, the following query is prohibited:

SELECT o.custid, c.name, MAX(o.payment)
FROM orders AS o, customers AS c
WHERE o.custid = c.custid
GROUP BY o.custid;

  SQL-1999 and higher allow such queries as an option, provided that these columns depend on the GROUP BY column (if they are functionally dependent on GROUP BY columns) in function - if such exist between the name and custid relationship, the query is legal, for example custid is a primary key customer of.

  MySQL 5.7.5 and later realized the function dependent detection. If ONLY_FULL_GROUP_BY SQL mode is enabled (default is), MySQL will refuse to do listed in Select, Having condition or ORDER BY list, there are references in the GROUP BY clause is neither named nor rely on their non-functionally aggregate column.

  Prior to 5.7.5, MySQL does not detect functional dependency, ONLY_FULL_GROUP_BY is not enabled by default. (No wonder I was 5.7.21, the default is not open.)

  When it is not enabled ONLY_FULL_GROUP_BY, MySQL would have to accept that the previous query. In this case, the server is free to choose any of the values ​​in each group, so unless they are the same, otherwise the selected value is uncertain, this may not be what you want.

  Further, the ORDER BY clause is added does not affect the value selected for each group. Sort out occurs after the set value is selected, and ORDER BY so does not affect how the server selected values ​​in each group.

  As you know, some attribute data, all values ​​of each non-polymeric unnamed column in a GROUP BY for each group is the same. At this prohibition ONLY_FULL_GROUP_BY may be useful.

 

  The following discussion shows the functional dependence, as well as an error message when the MySQL functionality missing dependency generated, and to allow MySQL to accept the way the query when the functional dependence missing.

  In ONLY_FULL_GROUP_BY mode, the following query may be illegal:

SELECT name, address, MAX(age) FROM t GROUP BY name;

  However, if the name is t of a primary key, or name is a unique, NOT NULL fields, the query will become legal. In this case, MySQL recognizes the functional dependency query column address and column group. For example, if the name is a primary key, its value determined address value, because each group has only one primary key, so that only one row. Therefore, MySQL selection of group address values ​​will not have randomness, it does not need to reject the query.

  Conversely, if the name is not t a primary key, or name is not a unique, NOT NULL fields, the query is illegal, because in this case, MySQL can not infer functional dependency and an error occurs:

ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUP
BY clause and contains nonaggregated column 'mydb.t.address' which
is not functionally dependent on columns in GROUP BY clause; this
is incompatible with sql_mode=only_full_group_by

  If you have to accept that MySQL queries, you can use ANY_VALUE () function:

SELECT name, ANY_VALUE(address), MAX(age) FROM t GROUP BY name;

  Of course, also be amplified move prohibited ONLY_FULL_GROUP_BY mode.

  However, the example here is very simple. In particular, we are unlikely to be grouped on a single primary key column, because each group contains only one row. For other examples demonstrate a "functional dependency" In a more complex query, reference 12.20.4.

 

  If a select query contains aggregate functions but no GROUP BY clause. Then in ONLY_FULL_GROUP_BY mode, it can not select list clause, the HAVING condition, ORDER BY columns list contains non-polymeric. As follows:

/*sql_mode=ONLY_FULL_GROUP_BY*/
mysql> SELECT name, MAX(age) FROM t;
ERROR 1140 (42000): In aggregated query without GROUP BY, expression
#1 of SELECT list contains nonaggregated column 'mydb.t.name'; this
is incompatible with sql_mode=only_full_group_by

  When the Group By clause does not exist, there is only one group, while not determine which name was chosen to be in this group. In this case, if the value of the name MySQL choice is irrelevant, ANY_VALUE () can come in handy:

/ * No error * / 
the SELECT ANY_VALUE (name), MAX (Age) the FROM T;

 

  In MySQL 5.7.5 and later in, ONLY_FULL_GROUP_BY will also affect the use DISTINCT and ORDER BY queries.

  It is assumed to have three c1, c2 and c3 table t, which includes the following:

/*

c1 c2 c3
1  2  A
3  4  B
1  2  C

*/

  Suppose we execute the following query, expected results sorted by c3 columns:

SELECT DISTINCT c1, c2 FROM t ORDER BY c3;

  To sort the results, you must first delete the duplicates. But to do this, we should keep the first line or the third line? This arbitrary choice will affect the retention of c3, c3 and retention in turn would affect the sort that have any sort of.

  To prevent this problem, if any ORDER BY expression does not meet at least one of the following conditions, there DISTINCT and ORDER BY queries will be rejected as invalid:

  • Expressions equal to a select list;
  • All cited the expression part of the query and the selected table columns, select all the elements of the list of China

 

  MySQL extended relative to the other standard SQL is: allowed referenced in the SELECT clause named alias Having clause.

  For example, the following query returns the name value appears once the line:

SELECT name, COUNT(name) FROM orders
GROUP BY name
HAVING COUNT(name) = 1;

  But after the MySQL extension can be used as follows:

SELECT name, COUNT(name) AS c FROM orders
GROUP BY name
HAVING c = 1;

NOTE: Prior to MySQL 5.7.5, enable ONLY_FULL_GROUP_BY will disable this extension, it is necessary to use a non-alias expression to write the HAVING clause.

  Press the front of my notes, Having clause is executed before the Select clause, it appears to be wrong? Experiment a bit, in my version (5.7.21) in doing so no problem (guess what, compile and order-related?):

select SID,count(SId) as n from sc group by SId having n=3;

/*

+------+---+
| SID  | n |
+------+---+
| 01   | 3 |
| 02   | 3 |
| 03   | 3 |
| 04   | 3 |
+------+---+

*/

 

  You can also mention, in standard SQL GROUP BY clause should only be allowed column expression (column expressions), and so therefore the statement is invalid because FLOOR (value / 100) is non-column expression (noncolumn expression):

SELECT id, FLOOR(value/100)
  FROM tbl_name
  GROUP BY id, FLOOR(value/100);

  The MySQL extends this, the above statement is valid.

  Standard SQL does not allow the GROUP BY clause appears aliases, MySQL is allowed. So the above query can be changed to:

SELECT id, FLOOR(value/100) AS val
  FROM tbl_name
  GROUP BY id, val;

  This is considered val column expression.

 

  When the non-column expression appears in the GROUP BY, MySQL recognizes the equality between the expression and the Select clause list of expressions. This means ONLY_FULL_GROUP_BY SQL mode is enabled, contain GROUP BY id, FLOOR (value / 100) the query is valid, because there has been the same FLOOR () expression Select list.

  However, MySQL does not attempt to identify the GROUP BY function dependent on a non-column expression (functional dependence), so the following query is not valid when you enable ONLY_FULL_GROUP_BY, even if the Select list of third expression is a simple formula for the id column: id and GROUP BY in the FLOOR () are added. (I.e., id + FLOOR (value / 100) and the GROUP BY column does not exist function dependent)

SELECT id, FLOOR(value/100), id+FLOOR(value/100)
  FROM tbl_name
  GROUP BY id, FLOOR(value/100);

  The solution is to use a derived table:

SELECT id, F, id+F
  FROM
    (SELECT id, FLOOR(value/100) AS F
     FROM tbl_name
     GROUP BY id, FLOOR(value/100)) AS dt;

 

Guess you like

Origin www.cnblogs.com/bigbigbigo/p/10956898.html