2017-01-30 26 views
0

これは他の場所で回答されていて、私はそれを見ていないのですが謝罪します。これは私が見つけた最も近いものですが、私がやろうとしていることではありません。グループ内の最大値を持つすべてのレコードを更新するMySQL

MySQL - updating all records to match max value in group

私は約15,000行の生産のWebサーバー上のテーブルを持っています。 item_nameを別のレコードと共有するレコードが多数ありますが、item_metersは(通常は常にそうとは限りませんが)各行の一意の値です。 item_idは常に一意です。現在、すべてのレコードのitem_flagカラムに値「0」があります。

item_flagの値が「1」になるように、各item_nameグループ内で最大のitem_meters値を持つすべてのレコードを更新したいとします。ここ

はITEM_ID ASCによって順序付け表の簡易版である:

---------------------------------------------- 
        mytable 
---------------------------------------------- 
item_id | item_name | item_meters | item_flag 
--------+-----------+-------------+----------- 
001  | aaa  | 224   | 0 
002  | aaa  | 359   | 0 
003  | aaa  | 456   | 0 
004  | bbb  | 489   | 0 
005  | bbb  | 327   | 0 
006  | bbb  | 215   | 0 
007  | ccc  | 208   | 0 
008  | ccc  | 756   | 0 
009  | ccc  | 756   | 0 
--------+-----------+-------------+----------- 

所望の結果は、それぞれ、最大item_metersを有する各「AAA」のitem_flag欄に「1」を持つテーブルであろう「BBB」、このような最大item_meters、各「CCC」を有する最大item_meters、等を有する:

---------------------------------------------- 
        mytable 
---------------------------------------------- 
item_id | item_name | item_meters | item_flag 
--------+-----------+-------------+----------- 
001  | aaa  | 224   | 0 
002  | aaa  | 359   | 0 
003  | aaa  | 456   | 1 
004  | bbb  | 489   | 1 
005  | bbb  | 327   | 0 
006  | bbb  | 215   | 0 
007  | ccc  | 208   | 0 
008  | ccc  | 756   | 1 
009  | ccc  | 756   | 0 
--------+-----------+-------------+----------- 

(ケースで同一ITEM_NAME 同じitem_metersを有する2つの以上のレコードが存在する(例えばitem_id 008と00数値的に低いitem_id(item_idは常に一意)のレコードは、item_flagの値が「1」であり、数値的に高いitem_idの行はitem_flagの値が「0」であるレコードの場合に望ましい結果となる")

また、このデータベースは毎日新しい行が追加された本番Webサーバーの背後で実行されていますが、新しい行が追加されるたびにテーブルを更新する必要はありません。後で新しい行がパラメータの外側に追加されるかどうかにかかわらず、1回だけ必要なものです。私がこれを言及したのは、クエリが一度しか実行されないため、実行速度が大きな問題ではないからです。

ありがとうございます!より多くの情報を提供したり、質問を明確にすることができれば教えてください。

+0

はここで明確に予想される出力を行います。 –

+0

あなたはあなたの 'クエリ'を考え出しましたか?あなたのコードを私たちに教えてください。 –

+0

こんにちは@reds、返信する時間を取ってくれてありがとう。私が誤解していたら、すみません。期待される結果は、与えられた2番目のテーブルの例であり、item_flag = "1"を持つ希望の行を示しています –

答えて

2

私が取るアプローチは、更新したい行の値item_idを返すクエリ(SELECT文)を最初に書くことです。出発点として

item_metersの最大値を取得し、このような単純なクエリ:

SELECT m.item_name 
     , MAX(m.item_meters) AS max_item_meters 
    FROM my_table m 
    GROUP BY m.item_name 

我々はそれぞれの最安item_idを得るために、別のクエリでインライン・ビューとしてそのクエリを使用することができこれらitem_name

SELECT MIN(o.item_id) AS min_item_id 
    FROM (SELECT m.item_name 
       , MAX(m.item_meters) AS max_item_meters 
      FROM my_table m 
      GROUP BY m.item_name 
     ) n 
    JOIN my_table o 
     ON o.item_name = n.item_name 
    AND o.item_meters = n.max_item_meters 
    GROUP BY o.item_name, o.item_meters 

そして、我々は我々が返さitem_id値に関連付けられた行全体を取得し、インライン・ビューとしてそのクエリを使用することができます...

SELECT t.item_id 
     , t.item_name 
     , t.item_meters 
     , t.item_flag 
    FROM my_table t 
    JOIN (SELECT p.min_item_id 
      FROM (SELECT MIN(o.item_id) AS min_item_id 
         FROM (SELECT m.item_name 
            , MAX(m.item_meters) AS max_item_meters 
           FROM my_table m 
           GROUP BY m.item_name 
          ) n 
         JOIN my_table o 
         ON o.item_name = n.item_name 
         AND o.item_meters = n.max_item_meters 
        GROUP BY o.item_name, o.item_meters 
       ) p 
     ) q 
     ON q.min_item_id = t.item_id 

SELECTクエリが機能したら、それをUPDATEステートメントに変換します。SELECT ... FROMをUPDATEに置き換え、SET句を追加します。 (時には、私たちが更新しているテーブルへの参照を禁止するMySQLエラーを避けるため、インラインビューをさらに別のSELECTにラップする必要があります。)

UPDATE my_table t 
    JOIN (SELECT p.min_item_id 
      FROM (SELECT MIN(o.item_id) AS min_item_id 
         FROM (SELECT m.item_name 
            , MAX(m.item_meters) AS max_item_meters 
           FROM my_table m 
           GROUP BY m.item_name 
          ) n 
         JOIN my_table o 
         ON o.item_name = n.item_name 
         AND o.item_meters = n.max_item_meters 
        GROUP BY o.item_name, o.item_meters 
       ) p 
     ) q 
     ON q.min_item_id = t.item_id 
    SET t.item_flag = '1' 

目的は、既存のテーブルを更新するのではなく、結果セットを返すことはない場合、私たちはクエリを書くことができますし、外側は、同じインライン・ビューに参加して、0またはどちらかを返しませんitem_flag 1は、item_id試合我々は1としてフラグ付けたいものかどうかをテスト...

SELECT t.item_id 
     , t.item_name 
     , t.item_meters 
     , IF(q.min_item_id IS NULL,0,1) AS `item_flag` 
    FROM my_table t 
    LEFT 
    JOIN (SELECT p.min_item_id 
      FROM (SELECT MIN(o.item_id) AS min_item_id 
         FROM (SELECT m.item_name 
            , MAX(m.item_meters) AS max_item_meters 
           FROM my_table m 
           GROUP BY m.item_name 
          ) n 
         JOIN my_table o 
         ON o.item_name = n.item_name 
         AND o.item_meters = n.max_item_meters 
        GROUP BY o.item_name, o.item_meters 
       ) p 
     ) q 
     ON q.min_item_id = t.item_id 
+0

こんにちは、ありがとうございます。私はこれを試して、報告する! –

+0

3番目の選択クエリからこのエラーが表示されます。クエリ(1054)のエラー: 'on節'の 'o.max_item_meters'の不明な列 –

+0

は** '= n.max_item_meters' **になります。上記の行は、** '= n.item_name' **である必要があります。私の悪い。 – spencer7593

関連する問題