我需要根据DESC的TotalUsers选择TOP 3 Sports并将它们分组为Individual Sports。
我到目前为止所做的是
SELECT *
FROM (
SELECT R.Sports, R.RoomID ,R.Name,
COUNT(C.ChatUserLogId) AS TotalUsers,
ROW_NUMBER()
OVER (PARTITION BY R.SPORTS ORDER BY R.SPORTS DESC ) AS Rank
FROM Room R JOIN ChatUserLog C
ON R.RoomID = C.RoomId
GROUP BY
R.RoomID,
R.Name,
R.Sports
) rs WHERE Rank IN (1, 2, 3)
ORDER BY Sports, TotalUsers DESC
以下是SQL的输出
Sports RoomID Name TotalUsers Rank
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Aerobics 6670 Aerobic vs. Anaerobic Exercise: Which is Best to Burn more Fat? 17 1
Aerobics 7922 Is it okay to be fat if you’re fit? 13 2
Aerobics 6669 What is the best time of the day to do an aerobic work out? 7 3
Archery 7924 Who were the best archers in history? 8 1
Archery 7925 Should I get into shooting or archery? 7 2
Archery 7926 What advantages, if any, do arrows have over bullets? 6 3
Badminton 6678 Which is more challenging, physically and mentally: badminton or tennis? 9 1
Badminton 6677 Who is your favorite - Lee chong wei or Lin dan? 8 2
Badminton 6794 Which single athlete most changed the sport? 7 3
Billiards 6691 How to get great at billiards? 34 1
Billiards 6692 Why is Efren Reyes the greatest billiards and pool player of all time? 31 2
Boxing 6697 Mike Tyson: The greatest heavyweight of all time? 13 1
Boxing 6700 Who is considered the greatest boxer of all time? Why? 13 2
Boxing 6699 What is the greatest, most exciting boxing fight of all-time? 12 3
但我的查询并没有解决我的要求。我需要输出如下所示。以下输出选择TotalUsers并按运动对它们进行分组。
Sports TotalUsers
-----------------------
Billiards 34
Billiards 31
Aerobics 17
Aerobics 13
Aerobics 7
Boxing 13
Boxing 13
Boxing 12
感谢任何帮助。
答案 0 :(得分:1)
从所需数据的描述中,您似乎只想从子查询中选择两列:
SELECT rs.Sports, rs.TotalUsers
FROM (SELECT R.Sports, R.RoomID ,R.Name,
COUNT(C.ChatUserLogId) AS TotalUsers,
ROW_NUMBER() OVER (PARTITION BY R.SPORTS ORDER BY R.SPORTS DESC ) AS Rank
FROM Room R JOIN
ChatUserLog C
ON R.RoomID = C.RoomId
GROUP BY R.RoomID, R.Name, R.Sports
) rs
WHERE Rank IN (1, 2, 3)
ORDER BY Sports, TotalUsers DESC;
唯一的变化是外部查询选择了你想要的两列。
答案 1 :(得分:1)
您的代码看起来非常接近,但似乎有三个问题。
Over
子句您的OVER
子句中出现错误:
ROW_NUMBER() OVER(PARTITION BY R.SPORTS ORDER BY R.SPORTS DESC)
PARTITION BY
语句在重新启动每个分区的排名时是正确的。但是,在每个分区中,您按分区标准排序,这是不确定的(对于分区中的每个值,R.SPORTS必须相等,因此ORDER BY将不起作用)。相反,您想要的是按总用户排序。声明是:
ROW_NUMBER() OVER(PARTITION BY R.SPORTS ORDER BY COUNT(C.CHATUSERLOGID) DESC)
(如果您希望具有相同数量的用户的房间具有相同的排名,您也可以使用RANK()
代替ROW_NUMBER
。)
问题表明您正在寻求按如下方式订购结果集:
第一个标准要求内部选择语句中有一个新列:对于每个房间,该运动的任何房间的用户数最多?这可以写成:
MAX(COUNT(C.CHATUSERLOGID)) OVER (PARTITION BY R.SPORTS) MaxSportsUsers
如果此列可用,您可以按MaxSportsUsers降序排序,然后按Rank升序。
问题解决方案表明您只想要排名前三的运动,按其顶级会议室中的用户数量排名。因此,您需要对表单进行排名:
RANK() OVER (PARTITION BY CATEGORY ORDER BY MAX(COUNT(USERID)) OVER (PARTITION BY CATEGORY)) CategoryTop
但是 SQL Server不支持此,并且尝试它会引发错误"窗口函数不能在另一个窗口函数或聚合的上下文中使用"。
有一些替代方案。作为一个,请注意,如果我们针对内部查询(rs)运行SELECT TOP 3 SPORT, MAX(TotalUsers) MaxUsers FROM RS ORDER BY 2 DESC
,则查询将产生前三个运动和最高用户数。将这些记录加入体育赛事的RS将限制最终输出到前三项运动。
此方法要求从内部联接引用RS。为此,必须将嵌套查询(SELECT * FROM (SELECT...) rs
)转换为公用表表达式(WITH RS AS (SELECT...) SELECT * FROM RS
)。这允许查询WITH RS AS (SELECT...) SELECT * FROM RS JOIN (SELECT... FROM RS) R2...
一旦查询采用CTE格式,我们就可以加入CTE查询,即INNER JOIN (SELECT TOP 3 SPORT, MAX(TOTALUSERS) MaxSportsUsers FROM RS GROUP BY SPORT ORDER BY 2 DESC) RS2 ON RS2.SPORT = RS.SPORT
),保持ORDER BY
子句相同。内部联接将最终数据集限制为前3项运动。
将MaxSportsUsers
列移动到内部联接,可以从RS(以前是内部查询)中删除它。
结合上述内容,我们得到最终查询:
WITH RS AS
(
SELECT R.Sports, R.RoomID ,R.Name,
COUNT(C.ChatUserLogId) AS TotalUsers,
ROW_NUMBER() OVER (PARTITION BY R.SPORTS ORDER BY COUNT(C.ChatUserLogId) DESC ) AS Rank
FROM Room R
JOIN ChatUserLog C ON R.RoomID = C.RoomId
GROUP BY R.RoomID, R.Name, R.Sports
)
SELECT rs.Sports, rs.TotalUsers
FROM rs
INNER JOIN (
SELECT TOP 3 SPORTS, MAX(TOTALUSERS) MaxSportsUsers FROM RS GROUP BY SPORTS ORDER BY 2 DESC
) RS2 ON RS2.SPORTS = RS.SPORTS
WHERE Rank IN (1, 2, 3)
ORDER BY MaxSportsUsers DESC, RANK;
答案 2 :(得分:0)
如果你想要前三名,那就先获得前三名。这样的事情:
with top3Sports as (
select top 3 sports, count(chatUserLogId) users
from room r join chatUserLog c on r.roomId = c.roomId
group by sports
order by count(chatUserLogId) desc
)
select the fields you need
from top3Sports join other tables etc
这比你尝试的方法简单得多。但请记住,无论你采取什么方法,关系都会让你感到困惑。