PHP / MYSQL - 计算有多少连续的前几周结果与本周具有相同的值(音乐排行榜)

PHP / MYSQL - Counting How Many Consecutive Previous Weeks Results Have Same Value As Current Week (Music Charts)

我正在尝试(并且失败)悲惨地想出一个 mysql 查询来计算一首歌曲在过去连续几周内在同一排行榜上的次数。因此,例如,给定下面的数据集,我将如何编写一个 returns:

的查询(基于提供日期)
id song_name date chart_position
1 Dancing Queen 2020-01-19 1
2 Wannabe 2020-01-19 2
3 Dancing Queen 2020-01-12 1
4 Shape Of You 2020-01-12 2
5 Blinding Light 2020-01-05 1
6 Wannabe 2020-01-05 2
7 Blinding Light 2019-12-29 1
8 Shape Of You 2019-12-29 2
9 Blinding Light 2019-12-22 1
10 Wannabe 2019-12-22 2

所以给出一个简单的 select:

SELECT song_name, date, chart_position FROM table WHERE date = '2019-12-29' ORDER BY chart_position ASC

我们应该得到以下结果:

song_name date chart_position
Blinding Light 2019-12-29 1
Shape Of You 2019-12-29 2

但是需要添加额外的信息才能做到:

song_name date chart_position weeks_in_position movement (optional - same / new / up / down)
Blinding Light 2019-12-29 1 2 same
Shape Of You 2019-12-29 2 1 new

非常感谢您的帮助,因为我花了 6 个小时尝试通过大量在线搜索自行解决问题,但未能解决!谢谢你的时间。

您可以将新列添加到您的 table 以便于查询,例如 previous_chart_position 类型整数(相同/新/向上/向下的简单比较)和 chart_position_updatedat 日期时间到计算 weeks_in_position.

的时间差

很可能仍然可以进行一些优化,但以下将为您提供您所请求的所有输出。第一部分(CTE)主要用于计算歌曲在歌曲位置连续播放了多少周。第二部分用于计算与前一周相比的位置,方法是将 table 连接到前一周。

WITH RECURSIVE cte AS (
  SELECT id, song_name, 1 as weeks_in_position, chart_position, dt
  FROM charts WHERE dt='2019-12-29' 
  UNION ALL
  SELECT charts.id, charts.song_name, cte.weeks_in_position+1, charts.chart_position, charts.dt
  FROM cte 
  INNER JOIN charts ON charts.song_name = cte.song_name
  AND charts.chart_position = cte.chart_position
  AND cte.id <> charts.id
  AND DATEDIFF(cte.dt, charts.dt) <= 7
  AND DATEDIFF(cte.dt, charts.dt) > 0
)

SELECT * FROM (
    SELECT cte.song_name, cte.dt, 
    MAX(cte.weeks_in_position) OVER(PARTITION BY song_name) weeks_in_position,
    CASE 
        WHEN charts.dt IS NULL THEN 'new'
        WHEN cte.chart_position > charts.chart_position THEN 'up'
        WHEN cte.chart_position < charts.chart_position THEN 'down'    
        ELSE 'same'
    END AS movement
    FROM cte 
    LEFT JOIN charts 
    ON cte.song_name = charts.song_name
    AND DATE_ADD(charts.dt, INTERVAL 7 DAY)=cte.dt
) AS DATA
WHERE dt='2019-12-29' 

您可以在db fiddle中查看结果。