Putting this as simply as I can, I have the following table structure:
Date | Type | Title
Say Type
is a value in the range 1-10, I have 1,000s of records in the table, and I want the 5 most recent records of unique type. So the result would be something like:
Date | Type | Title
2009-06-04 14:32:00 | 4 | Zeppo
2009-06-04 14:31:00 | 2 | Groucho
2009-06-04 14:30:00 | 8 | Harpo
2009-06-04 14:29:00 | 5 | Gummo
2009-06-04 14:28:00 | 3 | Chico
Seems like I either want DISTINCT
to only apply to the Type
column, or I want a GROUP BY
which will apply after an ORDER BY
clause.
All in MySQL 4.
Am I missing something? The easy solution seems to be:
SELECT MAX(date) AS max_date, type, title
FROM table
GROUP BY
type
ORDER BY
max_date DESC
LIMIT 5
And it should be extremely fast.
Didn't test in for MySQL 4
, but in MySQL 5
this can be easily done.
You'll need to have some kind of a PRIMARY KEY
in your table for this to work.
SELECT l.*
FROM (
SELECT type,
COALESCE(
(
SELECT id
FROM mytable li
WHERE li.type= dlo.type
ORDER BY
li.type DESC, li.date DESC, li.id DESC
LIMIT 4, 1
), CAST(0xFFFFFFFF AS DECIMAL)) AS mid
COALESCE(
(
SELECT date
FROM mytable li
WHERE li.type= dlo.type
ORDER BY
li.type DESC, li.date DESC, li.id DESC
LIMIT 4, 1
), '9999-31-12') AS mdate
FROM (
SELECT DISTINCT type
FROM t_mytable dl
) dlo
) lo, t_mytable l
WHERE l.type >= lo.type
AND l.type <= lo.type
AND (l.date, l.id) >= (lo.mdate, lo.mid)
See this entry in my blog for more detail on how it works:
N
rows for a GROUP
in MySQL
.If you cannot add a PRIMARY KEY
to implement this solution, you may try using less efficient one using system variables:
SELECT l.*
FROM (
SELECT @lim := 5,
@cg := -1
) vars,
mytable l
WHERE CASE WHEN @cg <> type THEN @r := @lim ELSE 1 END > 0
AND (@r := @r - 1) >= 0
AND (@cg := type) IS NOT NULL
ORDER BY
type DESC, date DESC
It's described here:
Update:
If you don't want to select 5
records for each type (which would give 5 x number of types
records in the resultset), but instead want to select 5
latest records with distinct type (which would give 5
records in the resultset), use this query:
SELECT date, type, title
FROM mytable m
WHERE NOT EXISTS
(
SELECT 1
FROM mytable mi
WHERE mi.date > m.date
AND mi.type = m.type
)
ORDER BY
date DESC
LIMIT 5
If you have lots of types, this will be more efficient that using GROUP BY
, provided you have an index on date
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With