MySQL - SELECT Sorgusuna dayalı UPDATE sorgusu


501

Tarih-saat dayalı iki olay arasında bir ilişki olup olmadığını (aynı tablodan) kontrol etmek gerekir.

Bir veri kümesi, belirli olayların bitiş tarih saatini ve diğer veri kümesi diğer etkinlikler için başlangıç ​​tarih saatini içerecektir.

İlk olay ikinci olaydan önce tamamlanırsa, bunları bağlamak istiyorum.

Şimdiye kadar sahip olduğum şey:

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

Sonra onlara katılıyorum:

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

Daha sonra, validation_check alanımı temel alarak, SELECT iç içe yerleştirilmiş bir UPDATE sorgusu çalıştırabilir miyim?


2
Ne istediğini bilmiyorum? SQL Select ile nasıl güncelleme yapılacağını anlamaya mı çalışıyorsunuz?
RiddlerDev

Yanıtlar:


811

Aslında bunu iki yoldan biriyle yapabilirsiniz:

MySQL güncelleme birleştirme sözdizimi:

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 sözdizimi:

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)

Sizin için en doğal olanı seçin.


92
İlk form (join ile güncelleme) ikincisinden çok daha verimli olacaktır. Birincisi tek bir birleşim yaparken, ikincisi tableA'nın her satırı için seçme sorgusunu yürütür.
ColinM

16
İlk örnek olarak, bir iç birleşim kullanmamalısınız? Sol birleştirme sonucu, validation_check'in karşılık gelen bir tableB kaydı olmayan tableA kayıtları için null değerine ayarlanmasına neden olmaz mı?
Cerin

3
@Cerin evet bu benim başıma geldi. İç birleşim olmalı! Veya sadece katılma olarak bırakın. İç birleşiminiz yoksa, sol birleşim tüm tableA kayıtlarının güncelleneceği anlamına gelir! Bu çok tehlikeli!
CMCDragonkai

10
İlk için teşekkürler (y). Bu cevap 7 yaşından büyük olsa da. Neden kimse MySQL gibi bazı veritabanında çalışmadığını belirtti inanamıyorum. Bu hatayı alırsınız:You can't specify target table ___ for update in FROM clause SQL.sql
Jugali Lakota

1
Ayrıca, yakın zamana kadar ilk yaklaşımın tableA= olduğunda MySQL ile çalışmadığını unutmayın tableB. Ara sonucu saklamak için geçici bir tablo oluşturmak zorundasınız. (bir geçiş komut dosyası için benzer bir sorgu yazmak zorunda kaldı)
svvac

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

Umarım bu sizin için çalışır.


5
Bu açık ara en hızlı sorgu. Düzenleme: 22K satırları ile dest ve 4K satırları ile src olması, tamamlanması 1 saniyenin altında sürerken, en iyi cevap 60 saniyenin üzerinde.
Chris Dev

1
Evet, bu en hızlı sorgudur, BTW WHERE deyimini de ekleyebilirsiniz
robinmag

1
en hızlı her zaman iyi değil, bu güncelleme her durumda işe yaramaz, aslında bazı durumlarda beklenmedik bir davranışa sahip olacaksınız, tüm bu yüzden bir koşul koymayın ve bu bir katılmak değil
Emiliano

114

MySQL'de kolay:

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

58

Birisi hangi tabloyu hedefliyor olursa olsun verileri bir veritabanından diğerine güncellemek istiyorsa, bunu yapmak için bazı kriterler olmalıdır.

Bu, tüm seviyeler için daha iyi ve temiz:

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! Harika çalışıyor!

Yukarıdaki anlayışla, işinizi yapmak için ayarlanan alanları ve "açık" ölçütlerini değiştirebilirsiniz. Ayrıca, denetimleri gerçekleştirebilir, sonra geçici tablolara veri çekebilir ve tablo ve sütun adlarınızı değiştirerek yukarıdaki sözdizimini kullanarak güncelleştirmeyi çalıştırabilirsiniz.

Umarım çalışırsa, bana bildirmezsen. Senin için kesin bir sorgu yazacağım.


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 ;

Umarım bu iki tablo arasında eşleşmeniz ve güncellemeniz gereken bir durumda size yardımcı olacaktır.


12

Bu soruyu çok karmaşık bir birleşime kendi çözümümü ararken buldum. Bu, yararlı olabileceğini düşündüğüm sorunun daha karmaşık bir versiyonuna alternatif bir çözümdür.

Ben faaliyetler bir birimde numaralandırılmış ve birimleri bir düzeyde (bir dize ?? N ile tanımlanmış), böylece bir SKU yani L1U1A1 kullanarak faaliyetleri tanımlayabilirsiniz bir şekilde numaralandırılmış faaliyetler tablosunda ürün_id alanı doldurmak gerekiyordu. Bu SKU'lar daha sonra farklı bir tabloda saklanır.

Activity_id ve product_id'in bir listesini almak için aşağıdakileri belirledim: -

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)

Bu mysql içinde bir SELECT içine dahil etmek çok karmaşık olduğunu, bu yüzden geçici bir tablo oluşturdu ve güncelleme deyimi ile katıldı: -

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;

Umarım birisi bunu faydalı bulur


iki sorgu çok iş parçacıklı ortamda tutarlı sonuç vermeyebilir.
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];

4

Bunun gibi iç birleştirmeyi kullanarak başka bir tablodaki değerleri güncelleyebilirsiniz

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

Bu sorguyu nasıl kullanacağınızı öğrenmek için burayı izleyin http://www.voidtricks.com/mysql-inner-join-update/

veya bunu yapmak için select'i alt sorgu olarak kullanabilirsiniz

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

sorgu burada ayrıntılı olarak açıklanmıştır http://www.voidtricks.com/mysql-update-from-select/


4

Kullanabilirsiniz:

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

3

Aynı tablo için,

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

Bir tablonun kendisinde yinelenen girişler ile ilgili bir sorun vardı. Aşağıda yaklaşımlar benim için çalışıyor. Ayrıca sibaz tarafından da savunuldu.

Sonunda aşağıdaki sorguları kullanarak çözdüm:

  1. Seçme sorgusu geçici tabloya kaydedilir

    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. Geçici tablo, güncelleme sorgusuna eklenir.

    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 konusunda çok tecrübeli değilim, lütfen daha iyi bir yaklaşım öneriyoruz.

Yukarıdaki sorgular MySql sunucusu içindir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.