2009-08-11 11 views
335

Je dois vérifier (à partir de la même table) s'il y a une association entre deux événements basés sur la date et l'heure.MySQL - Requête UPDATE basée sur SELECT Query

Un ensemble de données contiendra la date et l'heure de fin de certains événements et l'autre ensemble de données contiendra la date de début pour d'autres événements.

Si le premier événement se termine avant le deuxième événement, je voudrais les lier.

Ce que j'ai à ce jour est:

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 

Puis je les rejoindre:

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 

Puis-je alors, en fonction de mon champ validation_check, exécutez une requête UPDATE avec la imbriquée SELECT?

+1

Je ne sais pas ce que vous demandez? Essayez-vous de comprendre comment faire une mise à jour avec un SQL Select? – RiddlerDev

Répondre

573

Vous pouvez réellement faire de deux façons:

mise à jour MySQL syntaxe de jointure:

update tableA a 
left join tableB b on 
    a.name_a = b.name_b 
set 
    validation_check = if(start_dts > end_dts, 'VALID', '') 

syntaxe ANSI SQL:

update tableA set validation_check = 
    (SELECT if(start_DTS > end_DTS,'VALID','') as validation_check 
     FROM tableA 
     LEFT JOIN tableB ON name_A = name_B 
     WHERE id_A = tableA.id_A) 

Pioche celui qu'on vous semble le plus naturel.

+75

Le premier formulaire (mise à jour avec jointure) va être un * lot * plus efficace que le second. Le premier ferait une seule jointure, tandis que le second exécuterait la requête select pour chaque ligne de tableA. – ColinM

+12

Pour le premier exemple, ne devriez-vous pas utiliser une jointure interne? La jointure de gauche n'at-elle pas pour résultat que validation_check soit défini sur null pour les enregistrements tableA sans enregistrement tableB correspondant? – Cerin

+3

@Cerin oui c'est ce qui m'est arrivé. Cela devrait être une jointure interne! Ou laissez juste comme joint. Si vous n'avez pas de jointure interne, la jointure à gauche signifie que tous les enregistrements de tableA seront mis à jour! C'est très dangereux! – CMCDragonkai

43

Si quelqu'un cherche à mettre à jour des données d'une base de données à une autre, quelle que soit la table ciblée, il doit y avoir des critères pour le faire.

Celui-ci est meilleure et propre à tous les niveaux:

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! Cela fonctionne très bien! Avec la compréhension ci-dessus, vous pouvez modifier les champs set et les critères "on" pour faire votre travail. Vous pouvez également effectuer les vérifications, puis extraire les données dans les tables temporaires, puis exécuter la mise à jour à l'aide de la syntaxe ci-dessus en remplaçant les noms de table et de colonne.

Espérons que cela fonctionne, sinon laissez-moi savoir. Je vais écrire une requête exacte pour vous.

195
UPDATE table1 dest, (SELECT * FROM table2 where id=x) src 
    SET dest.col1 = src.col1 where dest.id=x ; 

Espérons que cela fonctionne pour vous.

+2

C'est de loin la requête la plus rapide. Editer: Avait dest avec 22K rangs, et src avec 4K rangs, il a fallu moins de 1 sec pour terminer, tandis que le top répond sur 60 sec. –

+1

Oui, c'est la requête la plus rapide, BTW vous pouvez ajouter la clause WHERE aussi – robinmag

+0

Belle requête. 5 Star – Zubair

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

Espérons que cela vous aidera dans un cas où vous devez faire correspondre et mise à jour entre deux tables.

9

J'ai trouvé cette question dans la recherche de ma propre solution à une jointure très complexe. C'est une solution alternative, à une version plus complexe du problème, que je pensais être utile. J'ai dû remplir le champ product_id dans la table des activités, où les activités sont numérotées dans une unité, et les unités sont numérotées dans un niveau (identifié en utilisant une chaîne ?? N), de sorte que l'on puisse identifier les activités en utilisant une SKU c'est-à-dire L1U1A1. Ces SKU sont ensuite stockés dans une table différente.

j'ai identifié ce qui suit pour obtenir une liste des 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) 

Je trouve que cela était trop complexe pour incorporer dans une commande SELECT dans MySQL, donc je crée une table temporaire, et rejoint que avec la déclaration de mise à jour: -

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; 

J'espère que quelqu'un trouve cela utile

66

Facile dans MySQL:

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

J'ai une question similaire, et je me demande si je peux faire quelque chose de similaire avec ma situation: https://stackoverflow.com/questions/47948052/mysql-wordpress-records-update – MagicMiles

4

Vous pouvez mettre à jour les valeurs d'une autre table en utilisant jointure interne comme celui-ci

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

Suivez ici pour savoir comment utiliser cette requête http://www.voidtricks.com/mysql-inner-join-update/

ou vous pouvez utiliser select comme sous-requête pour ce faire

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

requête expliqué dans les détails ici http://www.voidtricks.com/mysql-update-from-select/

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

Vous pouvez utiliser:

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

Pour une même table,

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;