My desk is:
id home datetime player resource ---|-----|------------|--------|--------- 1 | 10 | 04/03/2009 | john | 399 2 | 11 | 04/03/2009 | juliet | 244 5 | 12 | 04/03/2009 | borat | 555 3 | 10 | 03/03/2009 | john | 300 4 | 11 | 03/03/2009 | juliet | 200 6 | 12 | 03/03/2009 | borat | 500 7 | 13 | 24/12/2008 | borat | 600 8 | 13 | 01/01/2009 | borat | 700
I need to choose a different home with the maximum datetime.
The result will be:
id home datetime player resource ---|-----|------------|--------|--------- 1 | 10 | 04/03/2009 | john | 399 2 | 11 | 04/03/2009 | juliet | 244 5 | 12 | 04/03/2009 | borat | 555 8 | 13 | 01/01/2009 | borat | 700
I tried:
-- 1 ..by the MySQL manual: SELECT DISTINCT home, id, datetime AS dt, player, resource FROM topten t1 WHERE datetime = (SELECT MAX(t2.datetime) FROM topten t2 GROUP BY home) GROUP BY datetime ORDER BY datetime DESC
It doesn't work though the database holds 187, but the result set has 130 rows. The result includes some duplicates of home.
-- 2 ..join SELECT s1.id, s1.home, s1.datetime, s1.player, s1.resource FROM topten s1 JOIN (SELECT id, MAX(datetime) AS dt FROM topten GROUP BY id) AS s2 ON s1.id = s2.id ORDER BY datetime
no Provide all records.
-- 3 ..something exotic:
There are various results.
#1st floor
SELECT c1, c2, c3, c4, c5 FROM table1 WHERE c3 = (select max(c3) from table) SELECT * FROM table1 WHERE c3 = (select max(c3) from table1)
#2nd floor
For SQL Server, try the following:
WITH cte AS ( SELECT home, MAX(year) AS year FROM Table1 GROUP BY home ) SELECT * FROM Table1 a INNER JOIN cte ON a.home = cte.home AND a.year = cte.year
#3rd floor
This is the MySQL version. Only one entry is printed, and there is a duplicate MAX (datetime) in one group.
You can test it here http://www.sqlfiddle.com/#!2/0a4ae/1
sample data
mysql> SELECT * from topten; +------+------+---------------------+--------+----------+ | id | home | datetime | player | resource | +------+------+---------------------+--------+----------+ | 1 | 10 | 2009-04-03 00:00:00 | john | 399 | | 2 | 11 | 2009-04-03 00:00:00 | juliet | 244 | | 3 | 10 | 2009-03-03 00:00:00 | john | 300 | | 4 | 11 | 2009-03-03 00:00:00 | juliet | 200 | | 5 | 12 | 2009-04-03 00:00:00 | borat | 555 | | 6 | 12 | 2009-03-03 00:00:00 | borat | 500 | | 7 | 13 | 2008-12-24 00:00:00 | borat | 600 | | 8 | 13 | 2009-01-01 00:00:00 | borat | 700 | | 9 | 10 | 2009-04-03 00:00:00 | borat | 700 | | 10 | 11 | 2009-04-03 00:00:00 | borat | 700 | | 12 | 12 | 2009-04-03 00:00:00 | borat | 700 | +------+------+---------------------+--------+----------+
MySQL version with user variables
SELECT * FROM ( SELECT ord.*, IF (@prev_home = ord.home, 0, 1) AS is_first_appear, @prev_home := ord.home FROM ( SELECT t1.id, t1.home, t1.player, t1.resource FROM topten t1 INNER JOIN ( SELECT home, MAX(datetime) AS mx_dt FROM topten GROUP BY home ) x ON t1.home = x.home AND t1.datetime = x.mx_dt ORDER BY home ) ord, (SELECT @prev_home := 0, @seq := 0) init ) y WHERE is_first_appear = 1; +------+------+--------+----------+-----------------+------------------------+ | id | home | player | resource | is_first_appear | @prev_home := ord.home | +------+------+--------+----------+-----------------+------------------------+ | 9 | 10 | borat | 700 | 1 | 10 | | 10 | 11 | borat | 700 | 1 | 11 | | 12 | 12 | borat | 700 | 1 | 12 | | 8 | 13 | borat | 700 | 1 | 13 | +------+------+--------+----------+-----------------+------------------------+ 4 rows in set (0.00 sec)
Accept the exit of the answer
SELECT tt.* FROM topten tt INNER JOIN ( SELECT home, MAX(datetime) AS MaxDateTime FROM topten GROUP BY home ) groupedtt ON tt.home = groupedtt.home AND tt.datetime = groupedtt.MaxDateTime +------+------+---------------------+--------+----------+ | id | home | datetime | player | resource | +------+------+---------------------+--------+----------+ | 1 | 10 | 2009-04-03 00:00:00 | john | 399 | | 2 | 11 | 2009-04-03 00:00:00 | juliet | 244 | | 5 | 12 | 2009-04-03 00:00:00 | borat | 555 | | 8 | 13 | 2009-01-01 00:00:00 | borat | 700 | | 9 | 10 | 2009-04-03 00:00:00 | borat | 700 | | 10 | 11 | 2009-04-03 00:00:00 | borat | 700 | | 12 | 12 | 2009-04-03 00:00:00 | borat | 700 | +------+------+---------------------+--------+----------+ 7 rows in set (0.00 sec)
#4th floor
You can also try this operation, and the performance will be better for large table query. It works when there are no more than two records for each house and their dates are different. A better general MySQL query is Michael La Voie's query above.
SELECT t1.id, t1.home, t1.date, t1.player, t1.resource FROM t_scores_1 t1 INNER JOIN t_scores_1 t2 ON t1.home = t2.home WHERE t1.date > t2.date
Or try it in the case of Postgres or a database providing analysis function
SELECT t.* FROM (SELECT t1.id, t1.home, t1.date, t1.player, t1.resource , row_number() over (partition by t1.home order by t1.date desc) rw FROM topten t1 INNER JOIN topten t2 ON t1.home = t2.home WHERE t1.date > t2.date ) t WHERE t.rw = 1
#5th floor
The fastest MySQL solution, no internal query, no GROUP BY:
SELECT m.* -- get the row that contains the max value FROM topten m -- "m" from "max" LEFT JOIN topten b -- "b" from "bigger" ON m.home = b.home -- match "max" row with "bigger" row by `home` AND m.datetime < b.datetime -- want "bigger" than "max" WHERE b.datetime IS NULL -- keep only if there is no bigger than max
explain:
Use the home column to connect the table to itself. Using LEFT JOIN ensures that all rows in table m appear in the result set. Matches b that are not in the table will have column b represented by NULL S.
Another condition on the JOIN requires that only rows with a value greater than m on the datetime column of b be matched.
Using the data published in the problem, the LEFT JOIN will produce the following pairs:
+------------------------------------------+--------------------------------+ | the row from `m` | the matching row from `b` | |------------------------------------------|--------------------------------| | id home datetime player resource | id home datetime ... | |----|-----|------------|--------|---------|------|------|------------|-----| | 1 | 10 | 04/03/2009 | john | 399 | NULL | NULL | NULL | ... | * | 2 | 11 | 04/03/2009 | juliet | 244 | NULL | NULL | NULL | ... | * | 5 | 12 | 04/03/2009 | borat | 555 | NULL | NULL | NULL | ... | * | 3 | 10 | 03/03/2009 | john | 300 | 1 | 10 | 04/03/2009 | ... | | 4 | 11 | 03/03/2009 | juliet | 200 | 2 | 11 | 04/03/2009 | ... | | 6 | 12 | 03/03/2009 | borat | 500 | 5 | 12 | 04/03/2009 | ... | | 7 | 13 | 24/12/2008 | borat | 600 | 8 | 13 | 01/01/2009 | ... | | 8 | 13 | 01/01/2009 | borat | 700 | NULL | NULL | NULL | ... | * +------------------------------------------+--------------------------------+
Finally, the WHERE clause retains only NULL pairs in column b (marked with * in the table above); this means that the row selected from m has the maximum value in the datetime column due to the second condition in the JOIN clause.
read SQL anti pattern: avoid the trap of database programming Get other SQL tips.