PHP / MYSQL - 计算有多少连续的前几周结果与本周具有相同的值(音乐排行榜)
PHP / MYSQL - Counting How Many Consecutive Previous Weeks Results Have Same Value As Current Week (Music Charts)
我正在尝试(并且失败)悲惨地想出一个 mysql 查询来计算一首歌曲在过去连续几周内在同一排行榜上的次数。因此,例如,给定下面的数据集,我将如何编写一个 returns:
的查询(基于提供日期)
- 歌名
- 日期
- 图表位置
- 前几周它处于相同位置的次数(如果答案为 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:
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中查看结果。
我正在尝试(并且失败)悲惨地想出一个 mysql 查询来计算一首歌曲在过去连续几周内在同一排行榜上的次数。因此,例如,给定下面的数据集,我将如何编写一个 returns:
的查询(基于提供日期)- 歌名
- 日期
- 图表位置
- 前几周它处于相同位置的次数(如果答案为 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:
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中查看结果。