6

これらのフィールドを持つゲーム テーブルがあります。

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

ランキング、ポイントの合計、および平均ポイントを取得することはできましたが、最後に入力された名前を取得するには、同じテーブルに再度参加する必要があると思いますが、少し間違っているようです。

これを行う方法はありますか?

4

5 に答える 5

3

Ranking FunctionsSQL-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;

デモ

電子メールが一意でない場合に備えて最高点の行を表示しているため、結果が異なることに注意してください。したがって、「Bob」ではなく「Test」です。

于 2013-06-23T21:17:37.423 に答える
2

以下は、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;
于 2013-06-23T21:27:57.617 に答える
0

@RegisteredUser からのソリューションのみが の制約を処理しているようnameです。ただし、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()とのどちらかを選択するのに十分な情報が質問にありませんdense_rank()

また、ウィンドウ関数と集計関数を混在させることができるため、このバージョンは他のバージョンよりも単純です。

于 2013-06-23T23:02:42.623 に答える