5

次のステートメントを使用して、同点のエントリを含む上位 10 のスコアを見つけるのに役立ちました。

select T.EntryID, T.CategoryID, T.Score
from (
   select EntryID, CategoryID, Score,
          dense_rank() over(order by Score) as rn
   from YourTable
 ) T
where T.rn <= 10

(ありがとう [mikael-eriksson]: https://stackoverflow.com/users/569436/mikael-erikson )

[質問]: MSSQL 上位 10 を選択していますが、値が重複している列が含まれていますサンプル データは次のとおりです。

EntryID CategoryID  Score
3036    1           85
3159    1           85
3039    1           84
3146    1           83
3225    1           82
3045    1           82
3047    1           80
3048    1           80
3049    1           80
3193    1           80
3098    1           80
3025    1           72
3082    1           70
3167    1           70
3122    1           67
3220    1           65
3080    1           65
3168    1           64
______________________
Total Entries >= 18

トップ 10 (またはトップ 100 などのトップ) の各カテゴリから少なくとも 1 つのエントリがあるという要件があり、この場合は 3 つのカテゴリがあります。

ここで行う必要があるのは、カテゴリごとに少なくとも 1 つのエントリを上位 10 に含めることだけです。つまり、上位 10 のスコアがすべてカテゴリ 1 からのもので、カテゴリが 3 つある場合、カテゴリ 1 から最低 2 つのスコアを削除する必要があります。カテゴリ 2 と 3 の両方の最高得点エントリを含めます。

結果からわかるように、すべてのエントリはカテゴリ 1 からのものであるため、結果セットから EntryID の 3220、3080、および 3168 を削除する必要があります。これらはスコアが最も低く、カテゴリ 2 に最高スコアのエントリと最高のエントリを含める必要があります。結果は次のようになります。

EntryID CategoryID  Score
3036    1           85
3159    1           85
3039    1           84
3146    1           83
3225    1           82
3045    1           82
3047    1           80
3048    1           80
3049    1           80
3193    1           80
3098    1           80
3025    1           72
3082    1           70
3167    1           70
3122    1           67
3019    3           60
3800    2           54
______________________
Total Entries >= 17

次のシナリオでも同じことが言えます。見やすくするために、上位 10 の代わりに上位 5 を見てみましょう。

EntryID CategoryID  Score
3036    1           85
3159    1           85
3039    1           84
3146    1           83
3225    1           82
3045    1           82
3019    3           60
______________________
Total Entries >= 7

この場合、エントリ 3225 と 3045 は最低スコアのエントリであるため、ドロップする必要があります (最低スコアのエントリであっても、3047 を含める必要があります。結果にはすべてのカテゴリからのエントリが必要です)。最高スコアのエントリを含める必要があります。カテゴリ 2 からのエントリの場合、次のようになると予想されます。

EntryID CategoryID  Score
3036    1           85
3159    1           85
3039    1           84
3146    1           83
3019    3           60
3800    2           54
______________________
Total Entries >= 6

そして、特定のカテゴリへのエントリがないシナリオがあるかもしれません。たとえば、カテゴリ 2 のエントリがないため、上記の上位 5 の元の結果セット (以下に含まれる) と同様に、結果には依然として上位 5 が含まれている必要があります。参考までに)

EntryID CategoryID  Score
3036    1           85
3159    1           85
3039    1           84
3146    1           83
3225    1           82
3045    1           82
3019    3           60
______________________
Total Entries >= 7

繰り返している場合はご容赦ください。理解できるように明確にしようとしているだけです ;)

私は本当に助けに感謝します!

4

1 に答える 1

8

ご覧のとおり、より洗練された方法で行をランク付けする必要があります。これにより、すべてのカテゴリの上位のエントリがその値に関係なく含まれ、上位のものではないエントリが全体的に含まれるようになります。ランキング。

私が提案しようとしているのは、最も効率的な解決策ではないかもしれませんが、うまくいくはずです。

WITH ranked1 AS (
  SELECT
    *,
    RankByCategory = DENSE_RANK() OVER (
      PARTITION BY CategoryID
      ORDER BY Score DESC
    )
  FROM YourTable
),
ranked2 AS (
  SELECT
    *,
    FinalRank = DENSE_RANK() OVER (
      ORDER BY
        CASE RankByCategory WHEN 1 THEN 1 ELSE 2 END,
        Score DESC
    )
  FROM ranked1
)
SELECT
  EntryID,
  CategoryID,
  Score
FROM ranked2
WHERE FinalRank <= @top_n
;

最初の CTE は、行をカテゴリ別にランク付けするため、それぞれのカテゴリでどのエントリがトップになるかがわかります。次のステップ (2 番目の CTE) はグローバル ランキングを取得することです。今回は、エントリがそのカテゴリでトップかどうかを考慮します。カテゴリのトップ値はより低いランキングを受け取るため、最終結果に確実に含まれます。(もちろん、カテゴリの数が、出力で受け取りたい個別の値の数を超えないようにする必要があります。)

これは、SQL Fiddle での実際の例です。

于 2012-08-19T10:11:54.827 に答える