3

データのグループがいくつかあります。各グループにはいくつかのpropertyフィールドがあります。例えば:

_________________________
| id  | value | property |  
--------------------------
| 1    |  2    |    3    |
--------------------------
| 2    |  2    |    3    |
--------------------------
| 3    |  2    |    3    |
--------------------------
| 4    |  2    |    4    |
-------------------------
| 5    |  2    |    4    |
--------------------------
| 6    |  2    |    4    |
--------------------------

id ASCwithで並べ替えられた2つの文字列と、 withproperty = 3で並べ替えられた2つの文字列id ASC1つのクエリで更新するにはどうすればよいですか?property = 4

property = 33行のうち2行をで更新し、3行のうち2行をで更新したいproperty = 4。例:ID 1と2の行、およびID 4と5の行、つまり、1つのクエリ
で異なる条件のデータのグループを更新したい

4

3 に答える 3

2

計算されたランクフィールドを使用してそれを行うことができます、例えば-

SELECT p1.*, COUNT(*) rank FROM properties p1
  LEFT JOIN properties p2
    ON p2.property = p1.property AND p2.id <= p1.id
  GROUP BY p1.property, p1.id

このクエリは、プロパティごとに行番号を持つデータセットを返します。

+------+-------+----------+------+
| id   | value | property | rank |
+------+-------+----------+------+
|    1 |     2 |        3 |    1 |
|    2 |     2 |        3 |    2 |
|    3 |     2 |        3 |    3 |
|    4 |     2 |        4 |    1 |
|    5 |     2 |        4 |    2 |
|    6 |     2 |        4 |    3 |
+------+-------+----------+------+

次に、ランク<3のレコードを更新する必要があります。

UPDATE properties p
  JOIN (SELECT p1.*, COUNT(*) rank FROM properties p1
          LEFT JOIN properties p2
            ON p2.property = p1.property AND p2.id <= p1.id
        GROUP BY p1.property, p1.id) r
  ON p.id = r.id
  SET p.value = 100 -- set new value here
  WHERE r.rank < 3
于 2012-08-13T14:31:22.683 に答える
1

2つの更新をそれぞれ2行に制限するつもりだと思います。ORDER BYLIMITを更新ステートメントで使用できます。

UPDATE yourtable
SET property = 'new_value'
WHERE value=2 AND property = 4
ORDER BY id ASC LIMIT 2


UPDATE yourtable
SET property = 'new_value'
WHERE value=2 AND property = 3
ORDER BY id DESC LIMIT 2

アップデート:

これを1つのクエリに強制するには、をJOIN介して更新するIDを取得するサブクエリに対して行う必要がありますUNION。これは合法だと思います:

UPDATE yourtable
  JOIN (
    (SELECT id FROM yourtable WHERE value=2 AND property=4 ORDER BY id ASC LIMIT 2)
    UNION ALL
    (SELECT id FROM yourtable WHERE value=2 AND property=3 ORDER BY id DESC LIMIT 2)
  ) updaterows ON yourtable.id = updaterows.id
SET property = 'new value'
于 2012-08-06T16:35:22.677 に答える
1

解決策は次のとおりです。次の説明を参照してください。

update 
  t,
  (select GROUP_CONCAT(ids) as matching_ids from (
    select 
      SUBSTRING_INDEX(GROUP_CONCAT(id order by id), ',', 2) AS ids
    from
      t
    where
      property in (3,4)
    group by
      property
    ) s1
  ) s2
set value=12345
where 
  FIND_IN_SET(id, matching_ids) > 0
;

t説明のために、テーブルがと呼ばれ、初期状態が次のようになっていると仮定します。

root@mysql-5.1.51> select * from t;
+----+-------+----------+
| id | value | property |
+----+-------+----------+
|  1 |     2 |        3 |
|  2 |     2 |        3 |
|  3 |     2 |        3 |
|  4 |     2 |        4 |
|  5 |     2 |        4 |
|  6 |     2 |        4 |
+----+-------+----------+

このクエリを実行した結果は次のとおりです。

root@mysql-5.1.51> select * from t;
+----+-------+----------+
| id | value | property |
+----+-------+----------+
|  1 | 12345 |        3 |
|  2 | 12345 |        3 |
|  3 |     2 |        3 |
|  4 | 12345 |        4 |
|  5 | 12345 |        4 |
|  6 |     2 |        4 |
+----+-------+----------+

クエリの簡単な説明:

ステートメントidを使用して、各プロパティの最初の2つを取得します。SUBSTRING_INDEX(GROUP_CONCAT(id order by id), ',', 2)

上記を組み合わせて、GROUP_CONCAT(ids) as matching_idsすべてidの有効なを取得します。

id最後に、結合されたテキスト内にあるテーブルのすべての行を更新しmatching_idsます。

ノート:

  • group_concat_max_len変数が十分に長いことを確認する必要があります。デフォルトは1024です。とにかく、あなたはおそらくこれを何百万もの中に入れたいと思うでしょう(私の答えに関係なく)。

  • クエリは最適にはほど遠いです。それはあなたの質問に答えますが、ここで最適なクエリを行うことはできません。

  • おそらく、2つまたは3つのクエリを含むトランザクションを使用したほうがよいでしょう。

幸運を!

于 2012-08-15T15:11:09.057 に答える