Mysql MAX/MIN from Group
return to DevMysqlThis is best illustrated by a simple example. In this example, we have two tables: searches and results. The same search may have different results at different points in time.
In this example, imagine we want to find the most recent result for each of the different results returned by a specific search term.
Code
Create the Two Tables with Simplified Test DataDROP TABLE IF EXISTS `searches`; CREATE TABLE IF NOT EXISTS `searches` ( id int(11) NOT NULL auto_increment, result_id int(11) DEFAULT NULL, terms varchar(16) NOT NULL, created DATETIME, PRIMARY KEY (`id`), KEY `k_result_id` (result_id), KEY `k_terms` (terms) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; INSERT INTO `searches` (result_id, terms, created) VALUES (1, 'hello', NOW()), (1, 'hello', NOW() - INTERVAL 1 DAY), (2, 'hello', NOW()), (2, 'hello', NOW() - INTERVAL 1 DAY); DROP TABLE IF EXISTS `results`; CREATE TABLE IF NOT EXISTS `results` ( id int(11) NOT NULL auto_increment, result varchar(16) NOT NULL, created DATETIME, PRIMARY KEY (`id`), KEY `k_result` (result) ) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ; INSERT INTO `results` (id, result, created) VALUES (1, 'world', NOW()), (2, 'dolly', NOW());
SELECT Queries for the Results We Want to Find (2 different solutions)
Note: we can easily substitute MIN for MAX
SELECT Search.id, Search.terms, Result.result, Search.created as searched_at FROM ( SELECT id, terms, result_id, MAX(created) as created FROM searches WHERE terms = 'hello' GROUP BY terms, result_id ) Search JOIN results as Result on Result.id = Search.result_id ORDER BY Search.created DESC LIMIT 5; SELECT DISTINCT Search.id, Search.terms, Result.result, Search.created as searched_at FROM searches Search JOIN ( SELECT MAX(created) as created FROM searches GROUP BY result_id ) AS s2 ON Search.created = s2.created JOIN results as Result on Result.id = Search.result_id WHERE Search.terms = 'hello' ORDER BY Search.created DESC LIMIT 5;
Test Results for First Query Above: first with MIN then with MAX
Note: searched_at dates differ by 1 day
mysql> SELECT Search.id, Search.terms, Result.result, Search.created as searched_at -> FROM ( -> SELECT id, terms, result_id, MIN(created) as created -> FROM searches -> WHERE terms = 'hello' -> GROUP BY terms, result_id -> ) Search -> JOIN results as Result on Result.id = Search.result_id -> ORDER BY Search.created DESC -> LIMIT 5; +----+-------+--------+---------------------+ | id | terms | result | searched_at | +----+-------+--------+---------------------+ | 1 | hello | world | 2010-09-29 12:15:39 | | 3 | hello | dolly | 2010-09-29 12:15:39 | +----+-------+--------+---------------------+ 2 rows in set (0.00 sec) mysql> SELECT Search.id, Search.terms, Result.result, Search.created as searched_at -> FROM ( -> SELECT id, terms, result_id, MAX(created) as created -> FROM searches -> WHERE terms = 'hello' -> GROUP BY terms, result_id -> ) Search -> JOIN results as Result on Result.id = Search.result_id -> ORDER BY Search.created DESC -> LIMIT 5; +----+-------+--------+---------------------+ | id | terms | result | searched_at | +----+-------+--------+---------------------+ | 1 | hello | world | 2010-09-30 12:15:39 | | 3 | hello | dolly | 2010-09-30 12:15:39 | +----+-------+--------+---------------------+ 2 rows in set (0.01 sec)
Query Analysis
mysql> EXPLAIN SELECT Search.id, Search.terms, Result.result, Search.created as searched_at FROM ( SELECT id, terms, result_id, MAX(created) as created FROM searches WHERE terms = 'hello' GROUP BY terms, result_id ) Search JOIN results as Result on Result.id = Search.result_id ORDER BY Search.created DESC LIMIT 5; +----+-------------+------------+--------+---------------+---------+---------+------------------+------+----------------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+--------+---------------+---------+---------+------------------+------+----------------------------------------------+ | 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 2 | Using filesort | | 1 | PRIMARY | Result | eq_ref | PRIMARY | PRIMARY | 4 | Search.result_id | 1 | | | 2 | DERIVED | searches | ref | k_terms | k_terms | 18 | | 3 | Using where; Using temporary; Using filesort | +----+-------------+------------+--------+---------------+---------+---------+------------------+------+----------------------------------------------+ 3 rows in set (0.00 sec)
[There are no comments on this page]