Sql server sql Server:按点数总和排名,按排名排序

Sql server sql Server:按点数总和排名,按排名排序,sql-server,Sql Server,我有一个包含以下字段的游戏表: ID Name Email Points ---------------------------------- 1 John john@aaa.com 120 2 Test bob@aaa.com 100 3 John john@bbb.com 80 4 Bob bob@aaa.com 50 5 John john@aaa.co

我有一个包含以下字段的游戏表:

ID    Name       Email      Points
----------------------------------
1     John     john@aaa.com    120
2     Test     bob@aaa.com     100
3     John     john@bbb.com    80
4     Bob      bob@aaa.com     50
5     John     john@aaa.com    80
我想通过电子邮件对他们进行分组(电子邮件表明,无论第2行和第4行的名字不同,这两个玩家都是相同的),并且有分数总和和结果中最后输入的名字,并以最高分和最低分对他们进行排名

我希望从示例表中得到以下结果:

Ranking     Name       Points   Games_Played      Average_Points 
------------------------------------------------------------------------------------------
 1          John        200         2                100
 2          Bob         150         2                75
 3          John        80          1                80
我可以获得排名、总分和平均分,但得到最后输入的名字我认为需要再次加入同一个表,这似乎有点错误


你知道怎么做吗?

我想这就是你需要的

select ROW_NUMBER() OVER (ORDER BY sum(r1.points) Desc) as Ranking,
    r1.name as Name,
    sum(r1.points) as Points,
    r3.gplayed as 'Games Played',
    r2.points 'Average Points'
from ranks r1
    join (select avg(points) as points, email from ranks group by email) r2 
        on r1.email = r2.email
    join (select email, count(*) as gplayed from ranks group by email) r3 
        on r1.email = r3.email
group by 
    r1.email, 
    r1.name, 
    r2.points, 
    r3.gplayed

这是一个。

显示名称和分组的电子邮件将导致使用例如MIN(名称)并导致重复的名称

Select Rank() over (order by Points desc) as Rank
,Name,Points,Games_Played,Average_Points
from
(
Select Min(Name) as Name,Email,Sum(Points) as Points
,Count(*) as Games_Played,AVG(Points) as Average_Points
From @a Group by Email
) a 
order by Rank

小提琴中有两行注释行,您应该取消注释以查看相同结果上的行为。

您可以从SQL Server 2005向上使用:

WITH Points 
     AS (SELECT Sum_Points = Sum(points) OVER ( 
                                 partition BY email), 
                Games_Played = Count(ID) OVER ( 
                                 partition BY email), 
                Average_Points = AVG(Points) OVER ( 
                                 partition BY email), 
                Rank = DENSE_RANK()  OVER ( 
                              Partition BY email Order By Points DESC),
                * 
         FROM   dbo.Game)
SELECT Ranking=DENSE_RANK()OVER(ORDER BY Sum_Points DESC), 
       Name, 
       Points=Sum_Points, 
       Games_Played,
       Average_Points
FROM   Points 
WHERE Rank = 1
Order By Sum_Points DESC;


请注意,结果是不同的,因为在电子邮件不唯一的情况下,我用最高点显示行,因此“Test”而不是“Bob”。

下面是针对SQL Server 2012+、2005到2008 R2和2000的单独解决方案:

2012+

CREATE TABLE #PlayerPoints
    ( ID INT PRIMARY KEY
    , Name VARCHAR(10) NOT NULL
    , Email VARCHAR(20) NOT NULL
    , Points INT NOT NULL);

INSERT INTO #PlayerPoints (ID, Name, Email, Points)
VALUES
      (1, 'John', 'john@aaa.com', 120)
    , (2, 'Test', 'bob@aaa.com', 100)
    , (3, 'John', 'john@bbb.com', 80)
    , (4, 'Bob', 'bob@aaa.com', 50)
    , (5, 'John', 'john@aaa.com', 80)

WITH BaseData
AS
    (SELECT ID
        , Email
        , Points
        , LastRecordName = LAST_VALUE(Name) OVER
            (PARTITION BY Email
            ORDER BY ID DESC
            ROWS UNBOUNDED PRECEDING)
    FROM #PlayerPoints)
SELECT Email
    , LastRecordName = MAX(LastRecordName)
    , Points = SUM(Points)
    , Games_Played = COUNT(*)
    , Average_Points = AVG(Points)
FROM BaseData
GROUP BY Email
ORDER BY Points DESC;
2005年至2008年R2

CREATE TABLE #PlayerPoints
    ( ID INT PRIMARY KEY
    , Name VARCHAR(10) NOT NULL
    , Email VARCHAR(20) NOT NULL
    , Points INT NOT NULL);

INSERT INTO #PlayerPoints (ID, Name, Email, Points)
VALUES
      (1, 'John', 'john@aaa.com', 120)
    , (2, 'Test', 'bob@aaa.com', 100)
    , (3, 'John', 'john@bbb.com', 80)
    , (4, 'Bob', 'bob@aaa.com', 50)
    , (5, 'John', 'john@aaa.com', 80)

WITH BaseData
AS
    (SELECT ID
        , Email
        , Name
        , ReverseOrder = ROW_NUMBER() OVER
            (PARTITION BY Email
            ORDER BY ID DESC)
    FROM #PlayerPoints)
SELECT pp.Email
    , LastRecordName = MAX(bd.Name)
    , Points = SUM(pp.Points)
    , Games_Played = COUNT(*)
    , Average_Points = AVG(pp.Points)
FROM #PlayerPoints pp
JOIN BaseData bd
    ON pp.Email = bd.Email
    AND bd.ReverseOrder = 1
GROUP BY pp.Email
ORDER BY Points DESC;
2000

CREATE TABLE #PlayerPoints
    ( ID INT PRIMARY KEY
    , Name VARCHAR(10) NOT NULL
    , Email VARCHAR(20) NOT NULL
    , Points INT NOT NULL);

INSERT INTO #PlayerPoints (ID, Name, Email, Points)
SELECT 1, 'John', 'john@aaa.com', 120
UNION ALL
SELECT 2, 'Test', 'bob@aaa.com', 100
UNION ALL
SELECT  3, 'John', 'john@bbb.com', 80
UNION ALL
SELECT 4, 'Bob', 'bob@aaa.com', 50
UNION ALL
SELECT 5, 'John', 'john@aaa.com', 80;

SELECT pp.Email
    , LastRecordName = MAX(sppmi.Name)
    , Points = SUM(pp.Points)
    , Games_Played = COUNT(*)
    , Average_Points = AVG(pp.Points)
FROM #PlayerPoints pp
JOIN 
    (SELECT spp.Email
        , spp.Name
    FROM #PlayerPoints spp
    JOIN 
        (SELECT Email
            , MaximumID = MAX(ID)
        FROM #PlayerPoints
        GROUP BY Email) mi
        ON spp.ID = mi.MaximumID) sppmi
    ON pp.Email = sppmi.Email
GROUP BY pp.Email
ORDER BY Points DESC;

似乎只有@RegisteredUser的解决方案能够处理
名称上的约束。但是,它需要SQL Server 2012,因此这里有一个更通用的解决方案:

      Select dense_rank() over (order by sum(points) desc) as ranking
             max(case when islastid = 1 then Name end) as Name, Email, Sum(Points) as Points, 
             Count(*) as Games_Played, AVG(Points) as Average_Points
      From (select g.*,
                   row_number() over (partition by email order by id desc) as islastid
            from games g
           ) t
      Group by Email;
问题中没有足够的信息,无法在
rank()
densite\u rank()
之间进行选择


此外,与其他版本相比,此版本更简单,因为您可以混合使用窗口函数和聚合函数。

非常好的答案。谢谢解决了我的问题,学到了一些新东西。不应该是Max(名字)吗?Min(name)的意思是什么?我会用email来表达清楚并省略这个名字,这取决于你使用最小或最大的名字,它在任何情况下都是一种随机的。我只是想知道Max或Min的功能是什么,因为它不是一个数字,它是否像字典排序一样工作?+1。您的解决方案是唯一正确处理对name的实际约束的解决方案。我确实认为这个解决方案是有限的,只依赖于SQL Server 2012中提供的功能,而OP中没有指定该功能。我还将添加一个2005+解决方案。并添加一个2000解决方案。