Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MySQL GROUP BY and HAVING

I'm grouping my results based on a column X and I want to return the rows that has highest Column Y's value in the group.

SELECT * 
FROM   mytable 
GROUP  BY col1 
HAVING col2 >= (SELECT MAX(col2) 
                FROM   mytable AS mytable2 
                WHERE  mytable2.col1 = mytable.col1 GROUP BY mytable2.col1) 

I want to optimize the query above. Is it doable without sub-queries?

I found the solution and it's simpler than you think:

SELECT * FROM (SELECT * FROM mytable ORDER BY col2 DESC) temp GROUP BY col1

Runs in 5 milliseconds on 20,000 rows.

like image 558
Elie Avatar asked Feb 25 '11 01:02

Elie


People also ask

What is GROUP BY and HAVING in MySQL?

The HAVING clause is used instead of WHERE with aggregate functions. While the GROUP BY Clause groups rows that have the same values into summary rows. The having clause is used with the where clause in order to find rows with certain conditions. The having clause is always used after the group By clause.

Can we use GROUP BY and HAVING together?

You can apply a HAVING clause only to columns that also appear in the GROUP BY clause or in an aggregate function.

Do you need to use GROUP BY with HAVING?

Having can be used without groupby clause,in aggregate function,in that case it behaves like where clause. groupby can be used without having clause with the select statement.

Does GROUP BY go before or after HAVING?

If you specify both GROUP BY and HAVING, then they can appear in either order."


2 Answers

Using a derived table/inline view for a JOIN:

SELECT x.* 
  FROM mytable x
  JOIN (SELECT t.col1,
               MAX(t.col2) AS max_col2
          FROM MYTABLE t
      GROUP BY t.col1) y ON y.col1 = x.col1
                        AND y.max_col2 >= x.col2

Be aware that this will duplicate x records if there's more than one related y record. To remove duplicates, use DISTINCT:

SELECT DISTINCT x.* 
  FROM mytable x
  JOIN (SELECT t.col1,
               MAX(t.col2) AS max_col2
          FROM MYTABLE t
      GROUP BY t.col1) y ON y.col1 = x.col1
                        AND y.max_col2 >= x.col2

The following is untested, but will not return duplicates (assuming valid):

SELECT x.* 
  FROM mytable x
 WHERE EXISTS (SELECT NULL
                 FROM MYTABLE y
                WHERE y.col1 = x.col1
             GROUP BY y.col1
               HAVING MAX(y.col2) >= x.col2)
like image 160
OMG Ponies Avatar answered Oct 17 '22 04:10

OMG Ponies


Your Col2 never be > then MAX(col2) so i suggest to use col2 = MAX(col2)

so HERE is the QUERY

SELECT * FROM  mytable GROUP BY col1 HAVING  col2 = MAX(  col2 ) 
like image 21
Fisherman Avatar answered Oct 17 '22 04:10

Fisherman