Let's say I have a table similar to the following:
Item Description Time
----- ----------- -----
ItemA1 descript 08-16-2013 00:00:00
ItemA2 descript 08-16-2013 00:00:00
ItemA3 descript 08-16-2013 00:00:00
.
.
ItemAN descript 08-16-2013 00:00:00
ItemB1 descript 08-13-2013 00:00:00
ItemB2 descript 08-13-2013 00:00:00
ItemB3 descript 08-13-2013 00:00:00
.
.
ItemBN descript 08-13-2013 00:00:00
.
.
.
ItemX1 descript 01-13-2012 00:00:00
ItemX2 descript 01-13-2012 00:00:00
ItemX3 descript 01-13-2012 00:00:00
.
.
ItemXN descript 01-13-2012 00:00:00
Groups of items are added periodically. When a group of items is added they are all added with the same "Time" field. "Time" essentially serves as a unique index for that item group.
I want to SELECT the group of items that have the second highest time. In this example my query should pull the "B" items. I know I can do max(time
) to SELECT the "A" items, but I don't know how I would do second last.
My "Time" columns are stored as TIMESTAMP if that means anything.
SELECT MAX (column_name) FROM table_name WHERE column_name NOT IN (SELECT Max (column_name) FROM table_name); First we selected the max from that column in the table then we searched for the max value again in that column with excluding the max value which has already been found, so it results in the 2nd maximum value.
Select TOP 2 * from Products where Price = (Select Max(Price) from Products);
2nd highest value in SQL using Max () function SELECT MAX (ProductID) FROM Production. WorkOrder WHERE ProductID < (SELECT MAX (ProductID) FROM Production. WorkOrder);
If you do not include DISTINCT in a SELECT clause, you might find duplicate rows in your result, because SQL returns the JOB column's value for each row that satisfies the search condition. Null values are treated as duplicate rows for DISTINCT.
You can try something like:
SELECT MAX(Time)
FROM yourTable
WHERE Time < (SELECT MAX(Time) FROM yourTable)
SQLFiddle Demo
One approach:
SELECT t.*
FROM mytable t
JOIN ( SELECT l.time
FROM mytable l
GROUP BY l.time
ORDER BY l.time DESC
LIMIT 1,1
) m
ON m.time = t.time
This uses an inline view (assigned an alias of m) to return the second "greatest" time value. The GROUP BY gets us a distinct list, the ORDER BY DESC puts the latest first, and the "trick" is the LIMIT, which returns the second row. LIMIT(m,n) = (skip first m rows, return next n rows)
With that time value, we can join back to the original table, to get all rows that have a matching time value.
Performance will be enhanced with an index with leading column of time
. (I think MySQL should be able to avoid a "Using filesort" operation, and get the result from the inline view query fairly quickly.)
But, including a predicate in the inline view query, if you "know" that the second latest time will never be more than a certain number of days old, won't hurt performance:
WHERE l.time > NOW() + INTERVAL -30 DAYS
But with that added, then the query won't return the "second latest" group if it's time
is more than 30 days ago.
The SELECT MAX(time) WHERE time < ( SELECT MAX(time)
approach to get the second latest (the approach given in other answers) might be faster, especially if there is no index with leading column of time
, but performance would best be gauged by actual testing. The index with leading column of time will speed up the MAX() approach as well.)
The query I provided can be easily extended to get the 4th latest, 42nd latest, etc, by changing the LIMIT
clause... LIMIT(3,1)
, LIMIT(41,1)
, etc.
This should give you second biggest time:
SELECT time FROM table GROUP BY time ORDER BY time DESC LIMIT 1,1
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