我如何查询用户播放的前三首歌曲?

时间:2017-01-04 11:45:37

标签: mysql

如何查询用户播放的前3首歌曲? userid和song_name是char(255)

以下是对表格的描述:

 +-----------+-----------+------+-----+-------------------+-------+
 | Field     | Type      | Null | Key | Default           | Extra |
 +-----------+-----------+------+-----+-------------------+-------+
 | userid    | char(255) | YES  |     | NULL              |       |
 | song_name | char(255) | YES  |     | NULL              |       |
 | timestamp | timestamp | NO   |     | CURRENT_TIMESTAMP |       |
 +-----------+-----------+------+-----+-------------------+-------+

以下是表格的示例:

    +--------+-----------+---------------------+
    | userid | song_name | timestamp           |
    +--------+-----------+---------------------+
    | 123    | A         | 2017-01-04 01:35:41 |
    | 123    | B         | 2017-01-04 01:37:57 |
    | 123    | B         | 2017-01-04 01:38:32 |
    | 123    | B         | 2017-01-04 01:38:42 |
    | 123    | C         | 2017-01-04 01:38:46 |
    | 123    | D         | 2017-01-04 01:38:50 |
    | 123    | E         | 2017-01-04 01:38:54 |
    | 123    | E         | 2017-01-04 01:38:59 |
    | 123    | A         | 2017-01-04 01:39:03 |
    | 123    | E         | 2017-01-04 01:39:20 |

我将song_names更改为字母,以便您更好地理解。 最重要的歌曲是song_name对应用户ID的次数。

当前代码:

 SELECT userid, GROUP_CONCAT(DISTINCT song_name 
 ORDER BY song_name) 
 top_songs
 FROM sampleTable3
 GROUP BY userid; 

如何更改它会打印最常播放的前3首歌曲?

我的问题是询问特定值与用户ID对应的时间。

3 个答案:

答案 0 :(得分:1)

试试这个

select count(*) as cnt,song_name,userid from songs group by song_name order by cnt DESC limit 3;

demo on sqlfiddle

答案 1 :(得分:0)

实际上,你可以采用这种方法,但你需要先聚合并调整group_concat()逻辑:

SELECT userid,
       SUBSTRING_INDEX(GROUP_CONCAT(song_name ORDER BY cnt DESC SEPARATOR '|'), '|', 3)
 top_songs
FROM (SELECT userid, song_name, COUNT(*) as cnt
      FROM sampleTable3
      GROUP BY userid, song_name
     ) us
GROUP BY userid; 

但是,您可能会遇到字符串溢出错误,因为中间结果有限。您可以更改限制,这是一个系统参数。

另一种方法使用变量:

SELECT userid, GROUP_CONCAT(song_name ORDER BY cnt DESC SEPARATOR '|')
FROM (SELECT us.*,
             (@rn := if(@u = userid, @rn + 1,
                        if(@u := userid, 1, 1)
                       )
             ) as rn
      FROM (SELECT userid, song_name, COUNT(*) as cnt
            FROM sampleTable3
            GROUP BY userid, song_name
            ORDER BY userid, COUNT(*) DESC
           ) us CROSS JOIN
           (SELECT @u := -1, @rn := 0)
      GROUP BY userid
     ) u
WHERE rn <= 3;

答案 2 :(得分:0)

从戈登的回答中复制并修复。 (抱歉戈登)

SELECT userid, GROUP_CONCAT(song_name ORDER BY cnt DESC SEPARATOR '|')
FROM (SELECT us.*,
             (@rn := if(@u = userid, @rn + 1,
                        if(@u := userid, 1, 1)
                       )
             ) as rn
      FROM (SELECT userid, song_name, COUNT(*) as cnt
            FROM sampleTable3
            GROUP BY userid, song_name
            ORDER BY userid, COUNT(*) DESC
           ) us CROSS JOIN
           (SELECT @u := -1, @rn := 0) t1
     ) u
WHERE rn <= 3
GROUP BY userid;

如果您只想为一位特定用户查找前3首歌曲,请使用:

select userid, songname
from songs
where userid = 123
group by userid, songname
order by count(*) desc
limit 3;

SQLFiddle