Grouping by Expression Results

7.12.1 Problem

You want to group rows into subgroups based on values calculated from an expression.

7.12.2 Solution

Put the expression in the GROUP BY clause. For older versions of MySQL that don't support GROUP BY expressions, use a workaround.

7.12.3 Discussion

GROUP BY shares the property with ORDER BY that as of MySQL 3.23.2 it can refer to expressions. This means you can use calculations as the basis for grouping. For example, to find the distribution of the length of state names, group by LENGTH(name):

mysql> SELECT LENGTH(name), COUNT(*)
 -> FROM states GROUP BY LENGTH(name);
+--------------+----------+
| LENGTH(name) | COUNT(*) |
+--------------+----------+
| 4 | 3 |
| 5 | 3 |
| 6 | 5 |
| 7 | 8 |
| 8 | 12 |
| 9 | 4 |
| 10 | 4 |
| 11 | 2 |
| 12 | 4 |
| 13 | 3 |
| 14 | 2 |
+--------------+----------+

Prior to MySQL 3.23.2, you cannot use expressions in GROUP BY clauses, so the preceding query would fail. In Recipe 6.4, workarounds for this problem were given with regard to ORDER BY, and the same methods apply to GROUP BY. One workaround is to give the expression an alias in the output column list and refer to the alias in the GROUP BY clause:

mysql> SELECT LENGTH(name) AS len, COUNT(*)
 -> FROM states GROUP BY len;
+------+----------+
| len | COUNT(*) |
+------+----------+
| 4 | 3 |
| 5 | 3 |
| 6 | 5 |
| 7 | 8 |
| 8 | 12 |
| 9 | 4 |
| 10 | 4 |
| 11 | 2 |
| 12 | 4 |
| 13 | 3 |
| 14 | 2 |
+------+----------+

Another is to write the GROUP BY clause to refer to the output column position:

mysql> SELECT LENGTH(name), COUNT(*)
 -> FROM states GROUP BY 1;
+--------------+----------+
| LENGTH(name) | COUNT(*) |
+--------------+----------+
| 4 | 3 |
| 5 | 3 |
| 6 | 5 |
| 7 | 8 |
| 8 | 12 |
| 9 | 4 |
| 10 | 4 |
| 11 | 2 |
| 12 | 4 |
| 13 | 3 |
| 14 | 2 |
+--------------+----------+

Of course, these alternative ways of writing the query work in MySQL 3.23.2 and up as welland you may find them more readable.

You can group by multiple expressions if you like. To find days of the year on which more than one state joined the Union, group by statehood month and day, then use HAVING and COUNT( ) to find the non-unique combinations:

mysql> SELECT MONTHNAME(statehood), DAYOFMONTH(statehood), COUNT(*)
 -> FROM states GROUP BY 1, 2 HAVING COUNT(*) > 1;
+----------------------+-----------------------+----------+
| MONTHNAME(statehood) | DAYOFMONTH(statehood) | COUNT(*) |
+----------------------+-----------------------+----------+
| February | 14 | 2 |
| June | 1 | 2 |
| March | 1 | 2 |
| May | 29 | 2 |
| November | 2 | 2 |
+----------------------+-----------------------+----------+

Using the mysql Client Program

Writing MySQL-Based Programs

Record Selection Techniques

Working with Strings

Working with Dates and Times

Sorting Query Results

Generating Summaries

Modifying Tables with ALTER TABLE

Obtaining and Using Metadata

Importing and Exporting Data

Generating and Using Sequences

Using Multiple Tables

Statistical Techniques

Handling Duplicates

Performing Transactions

Introduction to MySQL on the Web

Incorporating Query Resultsinto Web Pages

Processing Web Input with MySQL

Using MySQL-Based Web Session Management

Appendix A. Obtaining MySQL Software

Appendix B. JSP and Tomcat Primer

Appendix C. References



MySQL Cookbook
MySQL Cookbook
ISBN: 059652708X
EAN: 2147483647
Year: 2005
Pages: 412
Authors: Paul DuBois

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net