PHP / MYSQL - 计算有多少连续的前一周结果与当前一周具有相同的价值(音乐图表)

Posted

技术标签:

【中文标题】PHP / MYSQL - 计算有多少连续的前一周结果与当前一周具有相同的价值(音乐图表)【英文标题】:PHP / MYSQL - Counting How Many Consecutive Previous Weeks Results Have Same Value As Current Week (Music Charts) 【发布时间】:2021-11-30 10:32:42 【问题描述】:

我正在苦苦尝试(但失败了)想出一个 mysql 查询来计算一首歌曲在之前连续几周内出现在同一图表位置的次数。例如,给定下面的数据集,我将如何编写一个查询(基于提供日期)返回:

歌曲名称 日期 图表位置 之前处于同一位置的周数(如果答案为 0 表示它在图表中上升或下降,则额外加分)
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 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 个小时里一直在尝试自己通过大量在线搜索来解决问题,但无法解决!感谢您的宝贵时间。

【问题讨论】:

【参考方案1】:

很可能仍然可以进行一些优化,但以下内容将为您提供您所要求的所有输出。第一部分(CTE)基本上是用来计算一首歌曲在歌曲位置的连续周数。第二部分用于计算与前一周相比的位置,方法是将表连接到前一周。

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查看结果。

【讨论】:

感谢这与一些调整完美地工作(加入更多的表格)。我非常感谢您的帮助@vixducis【参考方案2】:

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

【讨论】:

关系数据库的重点是不要有任何冗余数据。尽管 OP 的数据模型中已经存在冗余数据(最好将歌曲移动到单独的表中),但当您可以通过查询获得所需数据时,添加更多冗余并不是一个好的解决方案。 感谢@vixducis 的评论——我的数据实际上被分成了 2 个表(歌曲名称和信息在一个表中,而这个图表数据在另一个表中用 id 代替名称链接)。然而,为了便于理解这篇文章,我只是结合了这些信息(并计划根据需要自己稍微修改答案)。 :)

以上是关于PHP / MYSQL - 计算有多少连续的前一周结果与当前一周具有相同的价值(音乐图表)的主要内容,如果未能解决你的问题,请参考以下文章

sql函数--07---Mysql取前一天,前一周,后一天等时间函数

MySQL计算当前连续日期的连续日期

php截取一段文字的前一百个字的问题

根据单独的数字列计算连续周数

为什么rows这么大,在mysql explain中---写在去acumg听讲座的前一夜

查找连续周人员出现在表中