ウィンドウ関数がない場合、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では、必要な順序でテーブルのレコードを取得します。最初は日付順、次に値順です。  AとBtbl_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