2

Player と Shot の 2 つのテーブルがあります。Player と Shot の間には 1 対多の関係があります。Email、FirstName、LastName などのプレーヤー情報と、CalculatedScore、AccuracyScore、DistanceScore、TimeScore などのさまざまな部分を含むプレーヤーのトップ ショット情報を取得したいと考えています。CalculatedScore は最も重要な値です。他のすべてはそのスコアの構成要素です。

これが私の最善の努力です:

<!-- language: lang-sql -->
select s_max.PlayerId as playerId_max, s_max.TopScore, s.PlayerId, p.FirstName,
p.LastName, s.CalculatedScore, s.AccuracyScore, s.TimeScore, s.DistanceScore from Player p
inner join Shot s on s.PlayerId = p.Id
inner join (
    select distinct MAX(CalculatedScore) over (partition by PlayerId) as TopScore,
     PlayerId from Shot s2  
) s_max on s.PlayerId = s_max.PlayerId and s.CalculatedScore = s_max.TopScore
order by PlayerId desc

これは私が必要としているものとほとんど同じですが、トップ スコアに結びつく各行を返します。代わりに1行を返すようにするのは、驚くほどイライラします。

御時間ありがとうございます。

4

4 に答える 4

1

これは使用するのに適したケースだと思います。これは、特にテーブルの行数が少ないouter/cross apply場合、ウィンドウ関数を使用するよりも優れたパフォーマンスを発揮するはずです。Player

select
    p.Id, p.FirstName, p.LastName,
    s.CalculatedScore, s.AccuracyScore, s.TimeScore, s.DistanceScore
from Player as p
    outer apply (
        select top 1 s.*
        from Shot as s
        where s.PlayerId = p.Id
        order by s.CalculatedScore desc
    ) as s

ここに例を含むsql fiddleデモがあります。パフォーマンスを確認できます。

于 2013-09-03T16:13:33.680 に答える
1

私があなたを正しく理解していれば、これはあなたが望むものです:

;WITH CTE AS
(
    SELECT  *,
            RN=ROW_NUMBER() OVER(PARTITION BY PlayerId 
                                 ORDER BY CalculatedScore DESC)
    FROM Shot
)
SELECT  A.PlayerId as playerId_max, 
        B.TopScore, 
        A.FirstName,
        A.LastName, 
        B.CalculatedScore, 
        B.AccuracyScore, 
        B.TimeScore, 
        B.DistanceScore
FROM Player A
INNER JOIN CTE B
    ON A.PlayerId = B.PlayerId
WHERE B.RN = 1
于 2013-09-03T16:05:33.300 に答える
1

代わりに使用できますrow_number()(1 行を取得するため)。また、ウィンドウ関数を使用する場合、追加の結合は必要ありません。

select s.PlayerId , s.TopScore, s.PlayerId, p.FirstName,
       p.LastName, s.CalculatedScore, s.AccuracyScore, s.TimeScore, s.DistanceScore
from Player p inner join
     (select s.*,
             row_number() over (partition by s.PleryId order by CalculatedScore desc
                               ) as seqnum
      from Shot s
     ) s
     on s.PlayerId = p.Id and seqnum = 1
order by s.PlayerId desc
于 2013-09-03T16:06:19.063 に答える
0

ROW_NUMBER()これには次の関数を使用できます。

SELECT *
FROM (select   s_max.PlayerId as playerId_max
             , s_max.TopScore
             , s.PlayerId
             , p.FirstName
             , p.LastName
             , s.CalculatedScore
             , s.AccuracyScore
             , s.TimeScore
             , s.DistanceScore
             , ROW_NUMBER() OVER(PARTITION BY PlayerID ORDER BY CalculatedScore DESC)'RowRank'
        from Player p
        inner join Shot s 
            on s.PlayerId = p.Id
        order by PlayerId desc
        )sub
WHERE RowRank = 1
于 2013-09-03T16:05:42.043 に答える