Question

I have a table with four fields as follows,

(UID is User ID)

ID UID MUSIC DATE 
1   0   a   2013-10-20
2   0   a   2013-10-21
3   0   a   2013-10-22
4   0   a   2013-10-24
5   0   b   2013-10-11
8   0   b   2013-10-15
10  0   c   2013-10-26
9   0   c   2013-10-25
7   0   c   2013-10-20
6   0   c   2013-10-18
11  0   d   2013-10-10

How can I retrieve all second highest date from above table using MySQL Query?

Expected result:

ID UID MUSIC DATE 
3   0   a   2013-10-22
5   0   b   2013-10-11
9   0   c   2013-10-25

or

ID UID MUSIC DATE 
3   0   a   2013-10-22
5   0   b   2013-10-11
9   0   c   2013-10-25
11  0   d   2013-10-10
Was it helpful?

Solution

OK, I think I have the answer. Please check this:

SELECT tbl.ID, tbl.UID, tbl.MUSIC, tbl.DATE
FROM tbl
INNER JOIN
(
SELECT MUSIC,
       Substring_index(Substring_index(gdate, ',', 2), ',', -1) AS sec_date
FROM   (SELECT MUSIC               ,
               GROUP_CONCAT(DATE order by DATE desc separator ",") AS gdate
        FROM   tbl
        GROUP  BY MUSIC) t1
) AS tbl2
  ON tbl.MUSIC=tbl2.MUSIC
    AND tbl.DATE=tbl2.sec_date

First of all I've created GROUP_CONCAT on DATE, ordered by desc, so I can use Substring_index to get the second DATE, and of course, grouped everything by MUSIC, so the dates are grouped for respective MUSIC category. Then I wrote the actual query to get the results, with join to derived table so I ensure that I get correct row for that particular MUSIC AND DATE.

And here's the SQLFiddle

UPDATE

If you want to filter further by UID, just add WHERE to inner query, like this:

SELECT tbl.ID, tbl.UID, tbl.MUSIC, tbl.DATE
FROM tbl
INNER JOIN
(
SELECT MUSIC,
       Substring_index(Substring_index(gdate, ',', 2), ',', -1) AS sec_date
FROM   (SELECT MUSIC               ,
               GROUP_CONCAT(DATE order by DATE desc separator ",") AS gdate
        FROM   tbl
        WHERE UID=1 -- add filter here
        GROUP  BY MUSIC) t1
) AS tbl2
  ON tbl.MUSIC=tbl2.MUSIC
    AND tbl.DATE=tbl2.sec_date

and updated SQLFiddle

OTHER TIPS

From this SQLFiddle: http://sqlfiddle.com/#!2/fd47a2/7

SELECT tbl.UID, tbl.MUSIC, MAX(tbl.DATE)
FROM tbl
LEFT JOIN (
    SELECT UID, MUSIC, MAX(DATE) as DATE
    FROM tbl
    GROUP BY UID, MUSIC) AS tbl2
  ON tbl.UID = tbl2.UID
    AND tbl.MUSIC = tbl2.MUSIC
    AND tbl.DATE = tbl2.DATE
WHERE tbl2.UID IS NULL
GROUP BY tbl.UID, tbl.MUSIC

It does not however have the ID, which if you want, then IMO, you need to use the above query as yet another join to the original table to get the ID.

You can try the following query -

SELECT ID, UID, MUSIC, MAX(DATE) FROM TableName
WHERE DATE NOT IN (SELECT MAX(DATE) FROM TableName )

I think its something like finding second highest salary of employee - Example

There's probably a more elegant solution, but here's one way...

 SELECT a.* 
   FROM
      ( SELECT x.*
          FROM my_music x 
          JOIN my_music y 
            ON y.uid = x.uid 
           AND y.music = x.music 
           AND y.date >= x.date 
         GROUP 
            BY id
        HAVING COUNT(*) <= 2
      ) a
   JOIN
      ( SELECT x.*
          FROM my_music x 
          JOIN my_music y 
            ON y.uid = x.uid 
           AND y.music = x.music 
           AND y.date >= x.date 
         GROUP 
            BY id
        HAVING COUNT(*) <= 2
      ) b
     ON b.uid = a.uid
    AND b.music = a.music
    AND b.date <= a.date
  GROUP 
     BY id
 HAVING COUNT(*) = 1;

select id,music,[uid] from (select row_number() over ( PARTITION BY id order by [date] desc) as rn ,id,music,[uid] from table_name) a where rn = 2 -- insted of 2 u can change to any number u want

Try this

This is SQL Query

SELECT * FROM 
(SELECT 
ROW_NUMBER() OVER (PARTITION BY Music ORDER BY Date DESC) NO,
*
FROM UrTable) AS T1 WHERE no = 2
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top