Permintaan MySQL - PEMBARUAN berdasarkan SELECT Query

501

Saya perlu memeriksa (dari tabel yang sama) jika ada hubungan antara dua peristiwa berdasarkan tanggal-waktu.

Satu set data akan berisi tanggal berakhirnya waktu dari peristiwa tertentu dan set data lainnya akan berisi tanggal tanggal mulai untuk peristiwa lain.

Jika acara pertama selesai sebelum acara kedua maka saya ingin menghubungkan mereka.

Sejauh ini yang saya miliki adalah:

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

Lalu saya bergabung dengan mereka:

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

Bisakah saya, berdasarkan bidang validation_check saya, menjalankan kueri UPDATE dengan SELECT bersarang?

John M
sumber
2
Saya tidak yakin apa yang Anda minta? Apakah Anda mencoba mencari cara untuk melakukan pembaruan dengan SQL Select?
RiddlerDev

Jawaban:

811

Anda sebenarnya dapat melakukan ini dengan dua cara:

Pembaruan MySQL bergabung dengan sintaks:

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

Sintaks 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)

Pilih salah satu yang paling alami bagi Anda.

Eric
sumber
92
Bentuk pertama (pembaruan dengan bergabung) akan jauh lebih efisien daripada yang kedua. Yang pertama akan melakukan satu gabungan, sedangkan yang kedua akan menjalankan kueri pemilihan untuk setiap baris tableA.
ColinM
16
Sebagai contoh pertama, bukankah Anda harus menggunakan gabungan dalam? Tidakkah hasil gabung kiri di validation_check disetel ke nol untuk catatan tableA tanpa catatan tableB yang sesuai?
Cerin
3
@Cerin ya itu terjadi pada saya. Itu harus bergabung dalam! Atau biarkan saja seperti bergabung. Jika Anda tidak memiliki gabungan dalam, gabungan kiri berarti bahwa semua catatan tableA akan diperbarui! Ini sangat berbahaya!
CMCDragonkai
10
Terima kasih untuk yang pertama (y). Sementara jawaban ini lebih dari 7 tahun. Saya tidak percaya mengapa tidak ada yang menyatakan bahwa yang kedua tidak berfungsi di beberapa database seperti MySQL. Anda akan mendapatkan kesalahan ini:You can't specify target table ___ for update in FROM clause SQL.sql
Jugali Lakota
1
Juga, perhatikan bahwa sampai saat ini, pendekatan pertama tidak berfungsi dengan MySQL saat tableA= tableB. Anda terpaksa membuat tabel sementara untuk menyimpan hasil antara. (harus menulis permintaan serupa untuk skrip migrasi)
svvac
301
UPDATE
    `table1` AS `dest`,
    (
        SELECT
            *
        FROM
            `table2`
        WHERE
            `id` = x
    ) AS `src`
SET
    `dest`.`col1` = `src`.`col1`
WHERE
    `dest`.`id` = x
;

Semoga ini berhasil untuk Anda.

massquote
sumber
5
Sejauh ini, ini adalah permintaan tercepat. Sunting: Memiliki dest dengan baris 22K, dan src dengan baris 4K, butuh waktu kurang dari 1 detik untuk menyelesaikan, sedangkan jawaban teratas lebih dari 60 detik.
Chris Dev
1
Ya, ini adalah permintaan tercepat, BTW Anda dapat menambahkan klausa WHERE juga
robinmag
1
tercepat tidak selalu menyiratkan baik, pembaruan ini tidak akan berfungsi dalam semua kasus, pada kenyataannya beberapa kasus Anda akan memiliki perilaku yang tidak terduga, semua ini adalah mengapa tidak menempatkan kondisi dan itu bukan bergabung
Emiliano
114

Mudah di MySQL:

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

Jika seseorang berusaha memperbarui data dari satu basis data ke basis data lain, apa pun tabel yang mereka targetkan, pasti ada beberapa kriteria untuk melakukannya.

Yang ini lebih baik dan bersih untuk semua tingkatan:

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! Ini sangat bagus!

Dengan pemahaman di atas, Anda dapat memodifikasi bidang yang ditetapkan dan kriteria "on" untuk melakukan pekerjaan Anda. Anda juga dapat melakukan pemeriksaan, lalu menarik data ke tabel temp (s) dan kemudian menjalankan pembaruan menggunakan sintaksis di atas menggantikan nama tabel dan kolom Anda.

Semoga berhasil, jika tidak beri tahu saya. Saya akan menulis permintaan yang tepat untuk Anda.

KMX
sumber
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 ;

Semoga ini akan membantu Anda dalam kasus di mana Anda harus mencocokkan dan memperbarui antara dua tabel.

Mengenakan
sumber
12

Saya menemukan pertanyaan ini dalam mencari solusi saya sendiri untuk bergabung sangat kompleks. Ini adalah solusi alternatif, untuk versi masalah yang lebih kompleks, yang saya pikir mungkin bermanfaat.

Saya perlu mengisi bidang product_id di tabel aktivitas, di mana aktivitas diberi nomor dalam unit, dan unit diberi nomor dalam level (diidentifikasi menggunakan string ?? N), sehingga orang dapat mengidentifikasi aktivitas menggunakan SKU yaitu L1U1A1. SKU tersebut kemudian disimpan di tabel yang berbeda.

Saya mengidentifikasi hal-hal berikut untuk mendapatkan daftar activity_id vs 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)

Saya menemukan bahwa itu terlalu kompleks untuk dimasukkan ke dalam SELECT dalam mysql, jadi saya membuat tabel sementara, dan bergabung dengan pernyataan pembaruan: -

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;

Saya harap seseorang menemukan ini berguna

sibaz
sumber
dua kueri mungkin tidak memberikan hasil yang konsisten di lingkungan multi-utas.
donald
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];
Bhavik
sumber
4

Anda dapat memperbarui nilai dari tabel lain menggunakan gabungan dalam seperti ini

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];

Ikuti di sini untuk mengetahui cara menggunakan kueri ini http://www.voidtricks.com/mysql-inner-join-update/

atau Anda dapat menggunakan pilih sebagai subquery untuk melakukan ini

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

permintaan dijelaskan secara rinci di sini http://www.voidtricks.com/mysql-update-from-select/

Anand Roshan
sumber
4

Kamu bisa menggunakan:

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

Untuk meja yang sama,

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;
Gnanam pragasam
sumber
1

Saya punya masalah dengan entri duplikat dalam satu tabel itu sendiri. Di bawah ini adalah pendekatan yang berhasil untuk saya. Itu juga telah diadvokasi oleh @sibaz.

Akhirnya saya menyelesaikannya menggunakan pertanyaan di bawah ini:

  1. Kueri pemilihan disimpan dalam tabel temp

    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. Tabel temp digabungkan dalam kueri pembaruan.

    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
    )

Saya tidak terlalu berpengalaman dengan SQL, mohon saran pendekatan yang lebih baik lho.

Kueri di atas adalah untuk server MySql.

Rick
sumber