SQL分组和表值

时间:2016-08-21 04:39:32

标签: sql sql-server

我正在尝试为我的游戏挑选网站, 分数存储在SQL中。 游戏存储每个人的事件分数,因此每个玩家自然会有倍数。 我试图为每个球员收集顶部。 目前我正在使用分组

/**
 * Write a function that will take a string as input and output
 * a boolean (true or false) that describes if the string has valid parens.
 *
 * Use Cases:
 *
 * "" -> false
 *
 * null -> false
 *
 * "()" -> true
 *
 * ")" -> false
 *
 * "(" -> false
 *
 * "(())" -> true
 *
 * "())(" -> false
 *
 * "()))" -> false
 *
 * ")(" -> false 
 *
 * "()()" -> true
 */
public boolean validParen(String input) {
    // implementation? 
}

这很好,但是我想在网站上显示的信息中添加kill count。 我尝试将KillCount按部分添加到组中,但随后显示每个人的分数,因为每次尝试的杀戮计数都不同。

SELECT TOP(250) * 
  FROM
       ( SELECT CharName, CharType, MAX(Point) AS SCORE
           FROM SOD2RecBySandurr
       GROUP BY CharName, CharType) AS derivedtbl_1 
          WHERE CharName 
            NOT LIKE '\[GM\]%' ESCAPE '\' 
           AND SCORE NOT LIKE '0' 
       ORDER BY SCORE DESC

如何让它根据charname进行字符分组,但显示chartype和killcount, 如果我在选择中有killcount但在组中没有,那么它会抛出错误。

这个让我感到困惑:/我理解为什么它没有根据名称对它们进行分组(鉴于killcount不会与任何其他条目匹配)但我无法理解为什么它要求它在组中为选择功能。

编辑:

目前的结果是:

SELECT TOP(250) * 
  FROM
                (SELECT CharName, CharType, KillCount, MAX(Point) AS SCORE
                   FROM SOD2RecBySandurr
               GROUP BY CharName, CharType, KillCount) AS derivedtbl_1 
                  WHERE CharName 
                    NOT LIKE '\[GM\]%' ESCAPE '\' 
                    AND SCORE NOT LIKE '0' 
               ORDER BY SCORE DESC

我想看的地方

Player A - SCORE 1 - Kills 1
Player A - SCORE 2 - Kills 2
Player A - SCORE 3 - Kills 3
Player B - SCORE 1 - Kills 1

我想按最高分数排序,但包括该分数的杀人数

2 个答案:

答案 0 :(得分:1)

从我读到这个的方式来看,你想要在比赛中展示他们的顶级杀戮的前250名玩家?

首先,考虑使用OFFSET / FETCH来限制所使用的资源,并允许客户端指定查询的分页。有一些限制,但您可以阅读MSDN的ORDER BY CLAUSE来自行决定。

  • KILLCOUNT和POINT永远不会相同,请考虑在两列上使用MAX

您想要返回最佳得分手,因此也要保留范围内的最大杀伤力。根据您的会话范围(Map?Series?All-Time?),您可能需要使用SUM和/或OVER PARTITION BY子句{{1}不支持OVER子句直接} / OFFSET

考虑一下如何对它们进行分组,并且不会破坏组中的任何数据。因此,这些列需要聚合函数来提供任何用途(大多数情况下)。

如果你只是想要前250名得分手和他们的顶级杀手,一个解决方案可能如下:

FETCH

SELECT * FROM (SELECT CharName, CharType, MAX(KillCount) AS KillCount, MAX(Point) AS SCORE FROM SOD2RecB WHERE CharName NOT LIKE '\[GM\]%' ESCAPE '\' -- AND Point NOT LIKE '0' GROUP BY CharName, CharType HAVING MAX(Point) > 0) as SRC ORDER BY SCORE DESC FETCH FIRST 250 ROWS ONLY WHERE获取HAVING个参数。 SARG可能会根据因素运行更快的过滤组而不是行。但是,请考虑使用SQL Server子句。

更新(请参阅评论部分)当我写这篇文章时,我非常疲惫,所以可能会有错误。希望能够理解这一要点,以便您能够正确识别您的业务需求:

但是,如果您希望返回与MAX(Point)相关的KillCount列,则上述查询将无法保证您所记录的此结果。

对于组,删除不在WHERE中的列的关系。关于此主题的GROUP BY上有很多帖子更详细,但基本上您需要使用子查询,以便SO可以正确过滤返回的结果。

出于性能原因,存在简化算法的方法,但请注意将使用表扫描。表扫描不一定是坏的,但在每一行上运行完整的,未优化的查询会很糟糕,所以请考虑对查询的影响。

您可能会发现SQL Server在大数据集上而不是CTE上更快,但验证所使用的方法是否使用必要的最小比较(布尔值比数字更快,这肯定比字符串的隐式转换更快数据类型)和SARGable,你可以。

对于此示例,我选择使用OUTER APPLY而不是INNER JOIN纯粹作为方法的示例。主要思想是将组(CharName + CharType)的一个值(点)与返回到集合的最大值进行比较。绝对要考虑比较的基数。

OUTER APPLY

答案 1 :(得分:0)

在使用@clifton_h的答案已有一段时间之后,我重新评估了这一点, 我想出了如何获得相应的击杀数来匹配玩家得分最高的那一行:

我正在使用的Clifton_h的答案是:

SELECT CharName, CharType, KillCount, SCORE
            FROM (SELECT CharName, CharType, MAX(KillCount) AS KillCount, MAX(Point) AS SCORE
            FROM db.dbo.table
            GROUP BY CharName, CharType HAVING (MAX(Point) > 0)) AS SRC
            WHERE CharName NOT LIKE '\[GM\]%' ESCAPE '\' ORDER BY SCORE DESC;

但是,这给了我最大杀手数,这不一定与该玩家的最高得分有关。 我所做的是一条select语句,其中在顶层select中指定killcount列:

SELECT TOP(250) CharName, CharType, (SELECT KillCount FROM db.dbo.table WHERE Point=Score), Score
            FROM (SELECT CharName, CharType, MAX(Point) AS Score
            FROM db.dbo.table
            GROUP BY CharName, CharType HAVING (MAX(Point) > 0)) AS SRC
            WHERE CharName NOT LIKE '\[GM\]%' ESCAPE '\' ORDER BY SCORE DESC;

这基本上只是给我杀死计数,该计数与较低聚合的相应结果对齐。

还担任过内部联接:

SELECT a.CharName, a.CharType, a.KillCount, a.Point 
FROM db.dbo.table AS a 
JOIN (SELECT CharName, CharType, MAX(Point) AS Score FROM db.dbo.table GROUP BY CharType, CharName HAVING (MAX(Point) > 0)) AS b 
ON a.CharName = b.CharName AND a.CharType = b.CharType AND a.Point = b.Score ORDER BY Point DESC;