0

各ユーザーごとに n 個の最も古い注文を更新する必要があります。今のところ、次のコードを使用して、ユーザーごとに 1 つの最も古いレコードを更新しますが、n レコードを更新する方法がわかりません...

UPDATE orders
                INNER JOIN (
                    SELECT id, MIN(created) AS created
                    FROM orders 
                    WHERE status="queue" AND type="order"
                    GROUP BY user_id
                ) m ON orders.id = m.id
            SET orders.status = "process",
                orders.lock_id ="somehash"

私は答えを見つけました:

set @num := 0, @type := "";

UPDATE orders INNER JOIN(

SELECT id, user_id, created, row_number FROM (
   SELECT id, user_id, created,
      @num := if(@type = user_id, @num + 1, 1) AS row_number,
      @type := user_id AS dummy
  FROM orders
  WHERE status = "queue"
  ORDER BY user_id, created asc ) AS grouped_orders 
WHERE grouped_orders.row_number <= 2

) m ON orders.id = m.id SET orders.status = "process", orders.lock_id = "somehash";
4

2 に答える 2

2

これが驚くほど実行されるとは思いませんが、ROW_NUMBER()または他のウィンドウ関数を使用せず、ループを使用しないと (これよりもさらに悪い)、操作はより複雑になります。

UPDATE  Orders
        INNER JOIN
        (   SELECT  o1.ID
            FROM    Orders o1
                    LEFT JOIN Orders o2
                        ON o2.User_ID = o1.User_ID
                        AND o2.CreatedDate < o1.CreatedDate
            GROUP BY o1.ID
            HAVING  COUNT(*) < 3
        ) o
            ON orders.ID = o.ID
SET     Status = 1;

このn場合の は3条項のHAVINGです。User_ID ごとに少量のデータがある場合、これはうまく機能します。それぞれに何千もの行がある場合、クエリはすぐにかなり遅くなり、面倒になります。

SQL Fiddle の例

于 2012-06-07T11:08:41.573 に答える
1

クエリでlimitorder byを使用する方法を確認してください。これらは、各ユーザーの n 個の最も古いレコードを取得するのに役立ちます。

次に、これらの各エントリに対して行ったように、1 つに対して行ったように更新する必要があります。

次のようなクエリを使用する必要がある場合があります。

update table set WHAT_YOU_WANT_TO_SET
where table.id in (select id, etc from other_table USING_LIMIT_AND_ORDER_BY)
于 2012-06-07T11:01:51.907 に答える