MySQL-SELECTクエリに基づくUPDATEクエリ


501

(同じテーブルから)日時に基づいて2つのイベントの間に関連付けがあるかどうかを確認する必要があります。

1つのデータセットには特定のイベントの終了日時が含まれ、他のデータセットには他のイベントの開始日時が含まれます。

最初のイベントが2番目のイベントの前に完了する場合、それらをリンクしたいと思います。

これまでのところ、

SELECT name as name_A, date-time as end_DTS, id as id_A 
FROM tableA WHERE criteria = 1


SELECT name as name_B, date-time as start_DTS, id as id_B 
FROM tableA WHERE criteria = 2

次に、それらに参加します。

SELECT name_A, name_B, id_A, id_B, 
if(start_DTS > end_DTS,'VALID','') as validation_check
FROM tableA
LEFT JOIN tableB ON name_A = name_B

その後、validation_checkフィールドに基づいて、ネストされたSELECTを使用してUPDATEクエリを実行できますか?


2
あなたが何を求めているのか分かりませんか?SQL Selectで更新を行う方法を理解しようとしていますか?
RiddlerDev 2009

回答:


811

実際には、次の2つの方法のいずれかを実行できます。

MySQL更新結合構文:

UPDATE tableA a
INNER JOIN tableB b ON a.name_a = b.name_b
SET validation_check = if(start_dts > end_dts, 'VALID', '')
-- where clause can go here

ANSI SQL構文:

UPDATE tableA SET validation_check = 
    (SELECT if(start_DTS > end_DTS, 'VALID', '') AS validation_check
        FROM tableA
        INNER JOIN tableB ON name_A = name_B
        WHERE id_A = tableA.id_A)

最も自然に思える方を選択してください。


92
最初の形式(参加と更新)があることを行っている多くの秒よりも効率的。1つ目は単一の結合を実行し、2つ目はtableAのすべての行に対して選択クエリを実行します。
ColinM

16
最初の例では、内部結合を使用しないでください。左の結合は、対応するtableBレコードのないtableAレコードのvalidation_checkがnullに設定されないのですか?
セリン

3
@Cerinええ、私に起こりました。それは内部結合でなければなりません!または、そのままにしておいてください。内部結合がない場合、左結合はすべてのtableAレコードが更新されることを意味します!これはとても危険です!
CMCDragonkai、2015年

10
最初の(y)をありがとう。この答えは7年以上前のものですが。MySQLのような一部のデータベースでは2番目が機能しないと誰もが述べていないのはなぜでしょうか。このエラーが発生します:You can't specify target table ___ for update in FROM clause SQL.sql
Jugali Lakota

1
また、最近まで、最初のアプローチはtableA=の場合、MySQLでは機能しませんでしたtableB。中間結果を保存するための一時テーブルを作成する必要があります。(移行スクリプトに対して同様のクエリを作成する必要がありました)
svvac

301
UPDATE
    `table1` AS `dest`,
    (
        SELECT
            *
        FROM
            `table2`
        WHERE
            `id` = x
    ) AS `src`
SET
    `dest`.`col1` = `src`.`col1`
WHERE
    `dest`.`id` = x
;

これがうまくいくことを願っています。


5
これは断然最速のクエリです。編集:22K行のdestと4K行のsrcがあるため、完了するまでに1秒未満かかりましたが、トップの回答は60秒を超えました。
Chris Dev

1
はい、これは最速のクエリです。ところで、WHERE句も追加できます
robinmag

1
最速であるとは限らないため、この更新はすべてのケースで機能するわけではありません。実際、一部のケースでは予期しない動作が発生します。これらすべてが条件を入れないので、結合ではありません
Emiliano

114

MySQLで簡単:

UPDATE users AS U1, users AS U2 
SET U1.name_one = U2.name_colX
WHERE U2.user_id = U1.user_id

58

誰かが対象のテーブルに関係なく、あるデータベースから別のデータベースにデータを更新しようとしている場合、それを行うにはいくつかの基準が必要です。

これはすべてのレベルでより良く、きれいです:

UPDATE dbname1.content targetTable

LEFT JOIN dbname2.someothertable sourceTable ON
    targetTable.compare_field= sourceTable.compare_field
SET
    targetTable.col1  = sourceTable.cola,
    targetTable.col2 = sourceTable.colb, 
    targetTable.col3 = sourceTable.colc, 
    targetTable.col4 = sourceTable.cold 

やった!それはうまくいきます!

上記の理解があれば、設定したフィールドと「オン」基準を変更して作業を行うことができます。チェックを実行してから、データを一時テーブルにプルし、テーブルと列の名前を置き換える上記の構文を使用して更新を実行することもできます。

うまくいかない場合は、お知らせください。正確なクエリをお書きします。


24
UPDATE 
  receipt_invoices dest,
  (
    SELECT 
      `receipt_id`,
      CAST((net * 100) / 112 AS DECIMAL (11, 2)) witoutvat 
    FROM
      receipt 
    WHERE CAST((net * 100) / 112 AS DECIMAL (11, 2)) != total 
      AND vat_percentage = 12
  ) src 
SET
  dest.price = src.witoutvat,
  dest.amount = src.witoutvat 
WHERE col_tobefixed = 1 
  AND dest.`receipt_id` = src.receipt_id ;

これが2つのテーブル間で一致および更新する必要がある場合に役立つことを願っています。


12

この質問は、非常に複雑な結合に対する独自の解決策を探しているときに見つかりました。これは、問題のより複雑なバージョンに対する代替ソリューションです。

アクティビティテーブルのproduct_idフィールドにデータを入力する必要がありました。アクティビティはユニットで番号が付けられ、ユニットはレベルで番号が付けられ(文字列?? Nを使用して識別)、SKU、つまりL1U1A1を使用してアクティビティを識別できるようにします。これらのSKUは別のテーブルに格納されます。

activity_idとproduct_idのリストを取得するために、以下を特定しました:-

SELECT a.activity_id, w.product_id 
  FROM activities a 
  JOIN units USING(unit_id) 
  JOIN product_types USING(product_type_id) 
  JOIN web_products w 
    ON sku=CONCAT('L',SUBSTR(product_type_code,3), 'U',unit_index, 'A',activity_index)

mysql内のSELECTに組み込むには複雑すぎることがわかったので、一時テーブルを作成し、それをupdateステートメントで結合しました:-

CREATE TEMPORARY TABLE activity_product_ids AS (<the above select statement>);

UPDATE activities a
  JOIN activity_product_ids b
    ON a.activity_id=b.activity_id 
  SET a.product_id=b.product_id;

私は誰かがこれが便利だと思うことを望みます


マルチスレッド環境では、2つのクエリで一貫した結果が得られない場合があります。
ドナルド

7
UPDATE [table_name] AS T1,
      (SELECT [column_name] 
        FROM [table_name] 
        WHERE [column_name] = [value]) AS T2 
  SET T1.[column_name]=T2.[column_name] + 1
WHERE T1.[column_name] = [value];

4

このような内部結合を使用して、別のテーブルから値を更新できます

UPDATE [table1_name] AS t1 INNER JOIN [table2_name] AS t2 ON t1.column1_name] = t2.[column1_name] SET t1.[column2_name] = t2.column2_name];

このクエリを使用する方法を知るためにここに従ってくださいhttp://www.voidtricks.com/mysql-inner-join-update/

または、select as subqueryを使用してこれを行うことができます

UPDATE [table_name] SET [column_name] = (SELECT [column_name] FROM [table_name] WHERE [column_name] = [value]) WHERE [column_name] = [value];

クエリはここで詳細に説明されていますhttp://www.voidtricks.com/mysql-update-from-select/


4

以下を使用できます。

UPDATE Station AS st1, StationOld AS st2
   SET st1.already_used = 1
 WHERE st1.code = st2.code

3

同じテーブルの場合、

UPDATE PHA_BILL_SEGMENT AS PHA,
     (SELECT BILL_ID, COUNT(REGISTRATION_NUMBER) AS REG 
       FROM PHA_BILL_SEGMENT
        GROUP BY REGISTRATION_NUMBER, BILL_DATE, BILL_AMOUNT
        HAVING REG > 1) T
    SET PHA.BILL_DATE = PHA.BILL_DATE + 2
 WHERE PHA.BILL_ID = T.BILL_ID;

1

1つのテーブル自体に重複するエントリがあるという問題がありました。以下は私のために働いていたアプローチです。@sibazによっても提唱されています。

最後に、以下のクエリを使用してそれを解決しました:

  1. 選択クエリは一時テーブルに保存されます

    IF OBJECT_ID(N'tempdb..#New_format_donor_temp', N'U') IS NOT NULL
        DROP TABLE #New_format_donor_temp;
    
    select *
    into #New_format_donor_temp
    from DONOR_EMPLOYMENTS
    where DONOR_ID IN (
      1, 2
    )
    
    -- Test New_format_donor_temp
    -- SELECT *
    -- FROM #New_format_donor_temp;
  2. 一時テーブルは、更新クエリで結合されます。

    UPDATE de
    SET STATUS_CD=de_new.STATUS_CD, STATUS_REASON_CD=de_new.STATUS_REASON_CD, TYPE_CD=de_new.TYPE_CD
    FROM DONOR_EMPLOYMENTS AS de
      INNER JOIN #New_format_donor_temp AS de_new ON de_new.EMP_NO = de.EMP_NO
    WHERE
      de.DONOR_ID IN (
        3, 4
    )

SQLの経験があまりないので、あなたが知っているより良いアプローチをアドバイスしてください。

上記のクエリはMySqlサーバー用です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.