Truy vấn MySQL - CẬP NHẬT dựa trên Truy vấn CHỌN


501

Tôi cần kiểm tra (từ cùng một bảng) nếu có sự liên kết giữa hai sự kiện dựa trên thời gian.

Một bộ dữ liệu sẽ chứa thời gian ngày kết thúc của một số sự kiện nhất định và bộ dữ liệu khác sẽ chứa thời gian ngày bắt đầu cho các sự kiện khác.

Nếu sự kiện đầu tiên hoàn thành trước sự kiện thứ hai thì tôi muốn liên kết chúng lại.

Những gì tôi có cho đến nay là:

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

Sau đó tôi tham gia cùng họ:

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

Sau đó, tôi có thể, dựa trên trường verify_check của tôi, có thể chạy truy vấn CẬP NHẬT với CHỌN lồng nhau không?


2
Tôi không chắc chắn những gì bạn đang yêu cầu? Bạn đang cố gắng tìm ra cách thực hiện cập nhật với SQL Chọn?
RiddlerDev

Câu trả lời:


811

Bạn thực sự có thể làm điều này theo một trong hai cách:

Cú pháp tham gia cập nhật 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

Cú pháp 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)

Chọn bất cứ ai có vẻ tự nhiên nhất đối với bạn.


92
Hình thức đầu tiên (cập nhật với tham gia) sẽ hiệu quả hơn rất nhiều so với hình thức thứ hai. Cái đầu tiên sẽ thực hiện một phép nối duy nhất, trong khi cái thứ hai sẽ thực hiện truy vấn chọn cho mỗi hàng của bảngA.
ColinM

16
Ví dụ đầu tiên, bạn không nên sử dụng một tham gia bên trong? Kết quả tham gia bên trái trong xác thực_check sẽ được đặt thành null cho các bản ghi bảngA mà không có bản ghi bảngB tương ứng?
Cerin

3
@Cerin yea đã xảy ra với tôi. Nó nên được tham gia bên trong! Hoặc chỉ để nó như tham gia. Nếu bạn không có tham gia bên trong, tham gia bên trái có nghĩa là tất cả các bản ghi bảngA sẽ được cập nhật! Điều này rất nguy hiểm!
CMCDragonkai

10
Cảm ơn vì người đầu tiên (y). Trong khi câu trả lời này là hơn 7 tuổi. Tôi không thể tin được tại sao không ai tuyên bố rằng cái thứ hai không hoạt động trong một số cơ sở dữ liệu như MySQL. Bạn sẽ nhận được lỗi này:You can't specify target table ___ for update in FROM clause SQL.sql
Jugali Lakota 9/11/2016

1
Ngoài ra, lưu ý rằng cho đến gần đây, cách tiếp cận đầu tiên không hoạt động với MySQL khi tableA= tableB. Bạn buộc phải tạo một bảng tạm thời để lưu trữ kết quả trung gian. (phải viết một truy vấn tương tự cho tập lệnh di chuyển)
svvac

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

Hy vọng điều này làm việc cho bạn.


5
Đây là truy vấn nhanh nhất. Chỉnh sửa: Có số phận với 22K hàng và src với các hàng 4K, chỉ mất chưa đến 1 giây để hoàn thành, trong khi câu trả lời hàng đầu trên 60 giây.
Chris Dev

1
Có, đây là truy vấn nhanh nhất, BTW bạn cũng có thể thêm mệnh đề WHERE
robinmag

1
nhanh nhất không phải lúc nào cũng ngụ ý tốt, bản cập nhật này sẽ không hoạt động trong mọi trường hợp, thực tế một số trường hợp bạn sẽ có hành vi bất ngờ, tất cả điều này là tại sao không đặt điều kiện và đó không phải là tham gia
Emiliano

114

Dễ dàng trong MySQL:

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

58

Nếu ai đó đang tìm cách cập nhật dữ liệu từ cơ sở dữ liệu này sang cơ sở dữ liệu khác cho dù họ đang nhắm mục tiêu vào bảng nào, thì phải có một số tiêu chí để thực hiện.

Điều này là tốt hơn và sạch sẽ cho tất cả các cấp:

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! Nó hoạt động rất tốt!

Với cách hiểu ở trên, bạn có thể sửa đổi các trường đã đặt và tiêu chí "bật" để thực hiện công việc của mình. Bạn cũng có thể thực hiện kiểm tra, sau đó kéo dữ liệu vào (các) bảng tạm thời và sau đó chạy cập nhật bằng cú pháp trên thay thế tên bảng và cột của bạn.

Hy vọng nó hoạt động, nếu không cho tôi biết. Tôi sẽ viết một truy vấn chính xác cho bạn.


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 ;

Hy vọng điều này sẽ giúp bạn trong trường hợp bạn phải khớp và cập nhật giữa hai bảng.


12

Tôi tìm thấy câu hỏi này trong việc tìm kiếm giải pháp của riêng tôi cho một sự tham gia rất phức tạp. Đây là một giải pháp thay thế, cho một phiên bản phức tạp hơn của vấn đề, mà tôi nghĩ có thể hữu ích.

Tôi cần phải điền vào trường Product_id trong bảng hoạt động, trong đó các hoạt động được đánh số trong một đơn vị và các đơn vị được đánh số theo cấp độ (được xác định bằng chuỗi ?? N), để người ta có thể xác định các hoạt động bằng SKU tức là L1U1A1. Những SKU đó sau đó được lưu trữ trong một bảng khác.

Tôi đã xác định các mục sau để nhận danh sách 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)

Tôi thấy rằng điều đó quá phức tạp để kết hợp vào một CHỌN trong mysql, vì vậy tôi đã tạo một bảng tạm thời và kết hợp nó với câu lệnh cập nhật: -

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;

Tôi hi vọng ai đó thấy nó hữu ích


hai truy vấn có thể không cho kết quả nhất quán trong môi trường đa luồng.
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

Bạn có thể cập nhật giá trị từ một bảng khác bằng cách sử dụng phép nối bên trong như thế này

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

Theo dõi tại đây để biết cách sử dụng truy vấn này http://www.voidtricks.com/mysql-inner-join-update/

hoặc bạn có thể sử dụng select làm truy vấn con để làm điều này

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

truy vấn được giải thích chi tiết tại đây http://www.voidtricks.com/mysql-update-from-select/


4

Bạn có thể dùng:

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

3

Đối với cùng một bảng,

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

Tôi gặp vấn đề với các mục trùng lặp trong một bảng. Dưới đây là các phương pháp đã làm việc cho tôi. Nó cũng đã được ủng hộ bởi @sibaz.

Cuối cùng tôi đã giải quyết nó bằng các truy vấn dưới đây:

  1. Truy vấn chọn được lưu trong bảng tạm thời

    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. Bảng tạm thời được tham gia vào truy vấn cập nhật.

    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
    )

Tôi không có nhiều kinh nghiệm với SQL xin vui lòng tư vấn bất kỳ cách tiếp cận tốt hơn mà bạn biết.

Các truy vấn trên dành cho máy chủ MySql.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.