MySQL - ОНОВЛЕННЯ запиту на основі SELECT Query


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

Чи можу я тоді, спираючись на своє поле validation_check, запустити UPDATE-запит із вкладеним SELECT?


2
Я не впевнений, про що ви питаєте? Ви намагаєтеся зрозуміти, як зробити оновлення за допомогою SQL Select?
RiddlerDev

Відповіді:


811

Ви можете зробити це одним із двох способів:

Синтаксис приєднання оновлення 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
Перша форма (оновлення з приєднанням) буде набагато ефективнішою, ніж друга. Перший здійснив би одне об'єднання, тоді як другий виконає запит вибору для кожного рядка таблиціA.
ColinM

16
У першому прикладі, чи не слід використовувати внутрішнє з'єднання? Чи не буде результатом лівого з'єднання встановлено значення валідації_check для нульових записів tableA без відповідного запису tableB?
Серін

3
@Cerin так, що зі мною трапилося. Це має бути внутрішнє приєднання! Або просто залиште це як приєднатися. Якщо у вас немає внутрішнього з'єднання, ліве з'єднання означає, що всі записи таблиціA буде оновлено! Це дуже небезпечно!
CMCDragonkai

10
Дякую за перше (у). Хоча на цю відповідь більше 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
Це, безумовно, найшвидший запит. Редагувати: Маючи dest з 22K рядками та src з 4K рядками, на завершення пішло менше 1 секунди, тоді як верхня відповідь - понад 60 сек.
Кріс Дев

1
Так, це найшвидший запит, до речі, ви також можете додати пункт WHERE
robinmag

1
швидке не завжди означає добре, це оновлення не буде працювати у всіх випадках, адже в деяких випадках у вас буде несподівана поведінка, все це тому, що не ставите умову, і це не приєднання
Еміліано

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 

Трааа! Це чудово працює!

Маючи вищезгадане розуміння, ви можете змінювати встановлені поля та критерії "on", щоб виконати свою роботу. Ви також можете виконати перевірки, потім перетягнути дані в таблицю тем (ив), а потім запустити оновлення, використовуючи вищезазначений синтаксис, замінюючи назви ваших таблиць і стовпців.

Сподіваюся, це спрацює, якщо не дайте мені знати. Я напишу точний запит для вас.


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, тому я створив тимчасову таблицю і приєднав її до оператора оновлення: -

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/


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

У мене виникла проблема з повторюваними записами в одній самій таблиці. Нижче підходи працювали для мене. Його також виступав @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.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.