using of GROUP BY in mysql 8

2020-04-21 08:39发布

问题:

I have upgraded my MySQL server and now I have a problem with group by

select * from tickets WHERE `status` = 0 group by `tnumber` ORDER BY `created_at` DESC

error is:

SELECT list is not in GROUP BY clause and contains nonaggregated column

Updated: my table content is:

        <!DOCTYPE html>
        <html>
        <head>
        <style>
        table {
          font-family: arial, sans-serif;
          border-collapse: collapse;
          width: 100%;
        }

        td, th {
          border: 1px solid #dddddd;
          text-align: left;
          padding: 8px;
        }

        tr:nth-child(even) {
          background-color: #dddddd;
        }
        </style>
        </head>
        <body>

        <h2>id</h2>

        <table>
          <tr>
            <th>id</th>
            <th>tnumber</th>
            <th>title</th>
            <th>status</th>
          </tr>
          <tr>
            <td>1</td>
            <td>5c63e00a072c1</td>
            <td>1111</td>
            <td>1</td>
          </tr>
          <tr>
            <td>2</td>
            <td>5c63e00a072c1</td>
            <td>1111</td>
            <td>1</td>
          </tr>
          <tr>
            <td>3</td>
            <td>5c63e00a072c1</td>
            <td>1111</td>
            <td>1</td>
          </tr>
          <tr>
            <td>4</td>
            <td>5c63e00a072c1</td>
            <td>1111</td>
            <td>0</td>
          </tr>
          <tr>
            <td>5</td>
            <td>5c63ead5bd530</td>
            <td>2222</td>
            <td>1</td>
          </tr>
          <tr>
            <td>6</td>
            <td>5c63ead5bd530</td>
            <td>2222</td>
            <td>1</td>
          </tr>
        </table>

        <br/>
        I want to have following output:
        <br/>
        <br/>
        <br/>
        <table>
          <tr>
            <th>id</th>
            <th>tnumber</th>
            <th>title</th>
            <th>status</th>
          </tr>
          <tr>
            <td>1</td>
            <td>5c63e00a072c1</td>
            <td>1111</td>
            <td>0</td>
          </tr>
          <tr>
            <td>2</td>
            <td>5c63ead5bd530</td>
            <td>222</td>
            <td>1</td>
          </tr>
        </table>
        </body>
        </html>

My code is :

SELECT * FROM tickets 
WHERE `tnumber` IN ( 
                      SELECT tnumber FROM tickets GROUP BY tnumber
                   )  

but group by in second Select in where, doesn't have any affecs!!! How to do it in a propper way?

The GROUP BY statement is often used with aggregate functions (COUNT, MAX, MIN, SUM, AVG) to group the result-set by one or more columns.

回答1:

change your code from:

select * from tickets WHERE `status` = 0 group by `tnumber`;

To:

SELECT * from tickets where id in (SELECT max(id) FROM tickets GROUP BY tnumber) AND `status` = 0;


回答2:

Based on your question, it looks like that the query was working properly prior to MySql upgrade. Since you've upgraded MySql, default settings has been applied which means Only_Full_Group_By is enabled. Hence, if you want to execute queries like the one in question where non-aggregated columns in Select list are not in group by clause, you need to disable Only_Full_Group_By.

Run below statement & execute your query again:

SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));

Warning: You should only do this if you're sure that other non-aggreegated columns in select list are unique for each tnumber otherwise you'll get random rows as a result.

Following is quoted from MYSQL 8.0 Manual:

MySQL implements detection of functional dependence. If the ONLY_FULL_GROUP_BY SQL mode is enabled (which it is by default), MySQL rejects queries for which the select list, HAVING condition, or ORDER BY list refer to nonaggregated columns that are neither named in the GROUP BY clause nor are functionally dependent on them.

If ONLY_FULL_GROUP_BY is disabled, a MySQL extension to the standard SQL use of GROUP BY permits the select list, HAVING condition, or ORDER BY list to refer to nonaggregated columns even if the columns are not functionally dependent on GROUP BY columns. This causes MySQL to accept the preceding query. In this case, the server is free to choose any value from each group, so unless they are the same, the values chosen are nondeterministic, which is probably not what you want. Furthermore, the selection of values from each group cannot be influenced by adding an ORDER BY clause. Result set sorting occurs after values have been chosen, and ORDER BY does not affect which value within each group the server chooses. Disabling ONLY_FULL_GROUP_BY is useful primarily when you know that, due to some property of the data, all values in each nonaggregated column not named in the GROUP BY are the same for each group.

FOR More info, Click Here.



回答3:

If you are grouping by a column, the result will be aggregated row(s). As the error message says, it can't display non-aggregated rows with aggregated column. You can restructure your query like this:

SELECT `tnumber`
from tickets 
WHERE `status` = 0 
group by `tnumber` 
ORDER BY `tnumber` DESC

Update

If you want to fetch the record with MAX id then you can do the following:

SELECT `usrid` , `tnumber` , `title` , `message` , `status` , `created_at` , `type` 
FROM tickets 
WHERE status = 0
AND `id` IN (
    SELECT MAX(`id`)
    FROM tickets
);