MySQL - ปรับปรุงแบบสอบถามขึ้นอยู่กับแบบสอบถามที่เลือก


501

ฉันต้องการตรวจสอบ (จากตารางเดียวกัน) หากมีการเชื่อมโยงระหว่างสองเหตุการณ์ตามวันที่และเวลา

ชุดข้อมูลหนึ่งชุดจะมีวันที่สิ้นสุดเวลาของเหตุการณ์บางอย่างและชุดข้อมูลอื่นจะมีวันที่เริ่มต้นสำหรับกิจกรรมอื่น ๆ

หากเหตุการณ์แรกเสร็จสิ้นก่อนเหตุการณ์ที่สองฉันต้องการเชื่อมโยงพวกเขา

สิ่งที่ฉันมีอยู่คือ:

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

จากนั้นฉันจะสามารถเรียกใช้คิวรี UPDATE ที่มีซ้อนกันอยู่ในฟิลด์ validation_check ของฉันได้หรือไม่


2
ฉันไม่แน่ใจว่าสิ่งที่คุณถาม? คุณกำลังพยายามหาวิธีอัพเดตด้วย SQL Select หรือไม่?
RiddlerDev

คำตอบ:


811

คุณสามารถทำได้หนึ่งในสองวิธีนี้:

ไวยากรณ์เข้าร่วม MySQL update:

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
รูปแบบแรก (update กับเข้าร่วม) เป็นไปได้เป็นจำนวนมากมีประสิทธิภาพมากขึ้นกว่าที่สอง คนแรกจะเข้าร่วมเดียวในขณะที่คนที่สองจะดำเนินการแบบสอบถามเลือกสำหรับทุกแถวของ tableA
ColinM

16
สำหรับตัวอย่างแรกคุณไม่ควรใช้การรวมภายในหรือไม่ ผลลัพธ์การรวมทางซ้ายจะไม่ถูกต้อง validation_check ถูกตั้งค่าเป็นโมฆะสำหรับระเบียน tableA โดยไม่มีระเบียน tableB ที่สอดคล้อง
Cerin

3
@Cerin ใช่ที่เกิดขึ้นกับฉัน มันควรจะเข้าร่วมภายใน! หรือเพียงปล่อยไว้เป็นการเข้าร่วม หากคุณไม่มีการเข้าร่วมภายในการเข้าร่วมด้านซ้ายหมายความว่าระเบียน tableA ทั้งหมดจะได้รับการอัปเดต! มันอันตรายมาก!
CMCDragonkai

10
ขอบคุณสำหรับครั้งแรก (y) ในขณะที่คำตอบนี้มีอายุมากกว่า 7 ปี ฉันไม่อยากจะเชื่อเลยว่าทำไมไม่มีใครบอกว่าอันที่สองไม่ทำงานในฐานข้อมูลบางอย่างเช่น MySQL คุณจะได้รับข้อผิดพลาดนี้:You can't specify target table ___ for update in FROM clause SQL.sql
Jugali Lakota

1
นอกจากนี้ทราบว่าจนกระทั่งเมื่อเร็ว ๆ วิธีแรกไม่ได้ทำงานกับ MySQL เมื่อ=tableA 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 แถวและ src ที่มีแถว 4K ใช้เวลาดำเนินการไม่ถึง 1 วินาทีในขณะที่คำตอบยอดนิยมมากกว่า 60 วินาที
Chris Dev

1
ใช่นี่คือการสืบค้นที่เร็วที่สุด BTW คุณสามารถเพิ่ม WHERE clause ได้ด้วย
robinmag

1
เร็วที่สุดไม่ได้แปลว่าดีเสมอการอัปเดตนี้จะไม่ทำงานในทุกกรณีในความเป็นจริงบางกรณีคุณจะมีพฤติกรรมที่ไม่คาดคิดทั้งหมดนี้คือสาเหตุที่ไม่ใส่เงื่อนไขและนั่นไม่ใช่การเข้าร่วม
Emiliano


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 

Traaa! มันใช้งานได้ดี!

ด้วยความเข้าใจข้างต้นคุณสามารถปรับเปลี่ยนฟิลด์ที่ตั้งไว้และเกณฑ์ "เปิด" เพื่อทำงานของคุณ คุณยังสามารถทำการตรวจสอบจากนั้นดึงข้อมูลลงในตาราง temp แล้วเรียกใช้การปรับปรุงโดยใช้ไวยากรณ์ข้างต้นแทนที่ชื่อตารางและคอลัมน์ของคุณ

หวังว่ามันจะใช้ได้ถ้าไม่บอกให้ฉันรู้ ฉันจะเขียนคำถามที่ตรงกับคุณ


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 ;

หวังว่านี่จะช่วยคุณในกรณีที่คุณต้องจับคู่และอัปเดตระหว่างสองตาราง


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)

ฉันพบว่ามันซับซ้อนเกินไปที่จะรวมไว้ใน SELECT ภายใน mysql ดังนั้นฉันจึงสร้างตารางชั่วคราวและเข้าร่วมกับคำสั่ง 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;

ฉันหวังว่าบางคนพบว่ามีประโยชน์นี้


แบบสอบถามที่สองอาจไม่ให้ผลลัพธ์ที่สอดคล้องกันในสภาพแวดล้อมแบบมัลติเธรด
โดนัลด์

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 เป็นแบบสอบถามย่อยเพื่อทำสิ่งนี้

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/



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

ฉันมีปัญหากับรายการที่ซ้ำกันในตารางเดียว ด้านล่างเป็นวิธีการทำงานสำหรับฉัน มันยังได้รับการสนับสนุนโดย @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. ตาราง temp นั้นเข้าร่วมในแบบสอบถามแบบใช้ปรับปรุงข้อมูล

    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.