【问题标题】:Finding Top Values using SQL Query使用 SQL 查询查找最高值
【发布时间】:2021-09-08 11:05:08
【问题描述】:
对 SQL 相当陌生,我正在为一个音乐数据库编写一个练习查询,我需要在 2009 年 1 月按播放时间拉取前 10 首歌曲。这是架构:
到目前为止,这是我的声明。我只是想知道我是否朝着正确的方向前进,因为我知道为了创建查询,我需要对每首歌曲的播放时间求和,并将其包含在 ORDER BY 子句中:
SELECT song_name
FROM music LEFT JOIN client
ON music.id = client.music_id
WHERE client.date BETWEEN '2009-01-01' AND '2009-01-31'
ORDER BY SUM(client.playing_hrs) DESC;
【问题讨论】:
标签:
sql
database
join
select
data-analysis
【解决方案1】:
在 SQL Server 中,您可以使用此查询完成您的任务。请参阅我的答案底部,了解我在哪里解释了我在查询中做某些事情的更多原因,以便您可以将其应用于其他 RDBMS
select top(10) m.song_name,
total_song_hrs
from (
select m.song_name,
sum(c.playing_hrs) as total_song_hrs
from music m
join clients c
on m.id = c.music_id
where c.date >= '2009-01-01' and c.date <= '2009-01-31'
group by m.song_name
) s
order by total_song_hrs desc
首先,您需要将您的音乐表加入您的客户表,以便访问一首歌曲的播放小时数。然后,您将过滤掉所有在 2009 年 1 月之外播放时间的歌曲。然后您将按歌曲名称分组,以便汇总歌曲的播放时间。最后,您将上述内容包装在子查询中,在父查询中您需要使用排序依据,以便您可以选择前 10 首歌曲。
【解决方案2】:
根据您的 SQL 方言,您将需要某种 LIMIT 或 TOP 子句。 Microsoft SQL Server 使用 TOP。使用 GROUP BY 选择您的总金额也可能是有益的。
SELECT TOP 10 song_name,
SUM(client.playing_hrs) as hours_played
FROM music LEFT JOIN client
ON music.id = client.music_id
WHERE client.date BETWEEN '2009-01-01' AND '2009-01-31'
GROUP BY song_name
ORDER BY SUM(client.playing_hrs) DESC;
这将检索前十首歌曲及其播放时间。
【解决方案3】:
这是最好的窗口函数。
使用 OVER() 和 ROW_NUMBER() (ROW_NUMBER 函数的名称因 DBMS 而异,它适用于 sqlite 和 postgresql)
假设你有一个关系 R(a,b)
您可以通过升序使用 a 的值来获得前 10 个元组:
WITH T as (
SELECT a, b, row_number() over (order by a) as n FROM R)
select * from T where n <= 10;
在你的情况下,你可以这样做:
WITH R as (
SELECT song_name, sum(client.playing_hrs) as sum
FROM music LEFT JOIN client
ON music.id = client.music_id
WHERE client.date BETWEEN '2009-01-01' AND '2009-01-31'
),
T as (
SELECT song_name, row_number() over (order by sum desc) as n FROM R)
select * from T where n <= 10;
此外,您还可以获得每个元组的确切位置(1、2、3、...等)。
当然,您可以简化此查询。但是这个多步骤的子查询更清楚地显示了解决方案。
【解决方案4】:
您应该有一个带有聚合 SUM() 的 GROUP BY。