首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在这种情况下,如何按顺序和按组排序?

在这种情况下,如何按顺序和按组排序?
EN

Stack Overflow用户
提问于 2017-01-15 13:34:15
回答 3查看 116关注 0票数 1

我需要选择前3体育基于TotalUsers的DESC,并按个人体育分组。

到现在为止我所做的是

代码语言:javascript
运行
复制
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的输出

代码语言:javascript
运行
复制
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并根据体育对它们进行分组。

代码语言:javascript
运行
复制
Sports      TotalUsers
-----------------------
Billiards   34
Billiards   31
Aerobics    17
Aerobics    13
Aerobics    7
Boxing      13
Boxing      13
Boxing      12

任何帮助都是非常感谢的。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-01-15 16:41:18

您的代码看起来非常接近,但似乎有三个问题。

Over条款

您的OVER子句中似乎有一个错误:

代码语言:javascript
运行
复制
 ROW_NUMBER() OVER(PARTITION BY R.SPORTS ORDER BY R.SPORTS DESC)

PARTITION BY语句在重新启动每个分区的排序时是正确的。但是,在每个分区中,您是按照分区条件排序的,这是不确定的(对于分区中的每个值,R.SPORTS必然是相等的,因此ORDER不会产生任何影响)。相反,您想要的是由总用户订购。声明的内容如下:

代码语言:javascript
运行
复制
 ROW_NUMBER() OVER(PARTITION BY R.SPORTS ORDER BY COUNT(C.CHATUSERLOGID) DESC)

(您还可以使用RANK()代替ROW_NUMBER,如果您想要拥有相同数量的用户以获得相同的排名。)

最终查询排序

该问题表明您正在按以下顺序排列结果集:

  • 第一,根据体育;运动应该按该类别中最大的房间来订购。
  • 第二,每项运动的前3间房间按大小顺序排列。

第一个标准要求在您的内部选择语句中添加一个新列:对于每个房间,该运动的任何房间的用户人数最多的是什么?这可以写成:

代码语言:javascript
运行
复制
MAX(COUNT(C.CHATUSERLOGID)) OVER (PARTITION BY R.SPORTS) MaxSportsUsers

有了该列,您可以按MaxSportsUsers降序,然后按等级升序进行排序。

仅限于前三名:出现了一个问题

问题解决方案表明,您只想要前三项运动,按其顶部房间的用户数进行排名。因此,您需要对表单进行排序:

代码语言:javascript
运行
复制
RANK() OVER (PARTITION BY CATEGORY ORDER BY MAX(COUNT(USERID)) OVER (PARTITION BY CATEGORY)) CategoryTop

但是 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 (以前的内部查询)中删除它。

最终查询

结合上面的内容,我们得到了最后的查询:

代码语言:javascript
运行
复制
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;
票数 1
EN

Stack Overflow用户

发布于 2017-01-15 13:38:29

从所需数据的描述中,您似乎只想从子查询中选择两列:

代码语言:javascript
运行
复制
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
EN

Stack Overflow用户

发布于 2017-01-15 14:16:37

如果你想要前3名,先从前3开始。如下所示:

代码语言:javascript
运行
复制
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

这比你尝试过的方法简单得多。然而,请记住,无论你采取什么方法,领带都会把你搞砸。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41661666

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档