2

パネルデータセットがあります。つまり、、、、timesです。各日付の値に基づいてランキングを行いたいと思います。次のコマンドを実行するだけで、ソートを非常に簡単に実行できます。idsvalues

select * from tbl order by date, value

私が抱えている問題は、テーブルがこのように並べ替えられたら、各グループの行番号を取得するにはどうすればよいですか(つまり、日付ごとに、1からNまでのランキングという列が必要です)。

例:

入力:

Date, ID, Value
 d1, id1, 2
 d1, id2, 1
 d2, id1, 10
 d2, id2, 11

出力:

Date, ID, Value, Rank
 d1, id2, 1, 1
 d1, id1, 2, 2
 d2, id1, 10, 1
 d2, id2, 11, 2
4

3 に答える 3

3

ウィンドウ関数がない場合、tblユーザー変数を注文して使用して、パーティション (「日付」値) のランクを自分で計算できます。

SELECT "date",                                                -- D) Desired columns
       id,
       value,
       rank
  FROM (SELECT "date",                                        -- C) Rank by date
               id,
               value,
               CASE COALESCE(@partition, "date")
                 WHEN "date" THEN @rank := @rank + 1
                 ELSE             @rank := 1
               END AS rank,
               @partition := "date" AS dummy
          FROM (SELECT @rank := 0 AS rank,                    -- A) User var init
                       @partition := NULL AS partition) dummy
               STRAIGHT_JOIN
               (  SELECT "date",                              -- B) Ordering query
                         id,
                         value
                    FROM tbl
                ORDER BY date, value) tbl_ordered;

アップデート

では、そのクエリは何をしているのでしょうか。

ユーザー変数を使用して、並べ替えられた結果セットを「ループ」し、@rank現在の結果セット ( で追跡) のどの連続セグメントに応じてカウンター ( )をインクリメントまたはリセットし@partitionます。

クエリAでは、2 つのユーザー変数を初期化します。クエリBでは、必要な順序でテーブルのレコードを取得します。最初は日付順、次に値順です。 ABtbl_orderedを組み合わせて、次のような派生テーブル を作成します。

rank | partition | "date" |  id  | value 
---- + --------- + ------ + ---- + -----
  0  |   NULL    |   d1   |  id2 |    1
  0  |   NULL    |   d1   |  id1 |    2
  0  |   NULL    |   d2   |  id1 |   10
  0  |   NULL    |   d2   |  id2 |   11

dummy.rank列andについてはあまり気にしていないことを思い出してくださいdummy.partition— それらは、変数@rankandを初期化する方法の単なる偶然です@partition

クエリCでは、派生テーブルのレコードをループします。私たちがやっていることは、多かれ少なかれ、次の疑似コードが行うことです:

rank      = 0
partition = nil

foreach row in fetch_rows(sorted_query):
  (date, id, value) = row

  if partition is nil or partition == date:
    rank += 1
  else:
    rank = 1

  partition = date

  stdout.write(date, id, value, rank, partition)

最後に、クエリDは、 C からすべての列を射影しますが、保持している列(名前が付けられており、表示する必要はありません)を除きます。@partitiondummy

于 2011-12-06T05:35:25.513 に答える
1

これは古い質問であることは知っていますが、ここに短い答えがあります:

SELECT w.*, if(
      @preDate = w.date,
      @rank := @rank + 1,
      @rank := (@preDate :=w.date) = w.date
    ) rank
FROM tbl w
JOIN (SELECT @preDate := '' )a
ORDER BY date, value
于 2013-03-20T12:33:58.800 に答える
0

これでうまくいくでしょうか?

select [DATE],ID,Value, 
(DENSE_RANK()  OVER (   
   PARTITION BY ID
 ORDER BY Date) )AS [DenseRank],    
ROW_NUMBER() OVER ( PARTITION BY ID ORDER BY [Date] DESC) AS RN     
from SomeTable 
于 2011-12-06T01:46:05.157 に答える