sql >> データベース >  >> RDS >> Mysql

mysqlのグループソート内

    ウィンドウ関数がない場合は、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 およびB 一緒に派生テーブルtbl_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の列はあまり気にしないことを忘れないでください およびdummy.partition —これらは変数@rankを初期化する方法の偶然にすぎません および@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のすべての列を投影します 例外 @partitionを保持している列の場合 (dummyと名付けました 表示する必要はありません)。



    1. SQL Serverチュートリアル–Transact-SQLをマスターするために必要なすべて

    2. 集約MySQL関数は常に単一の行を返しますか?

    3. カンマ区切りの文字列をmysqlの行に分割します

    4. ミリ秒単位のCURRENT_TIMESTAMP