Précédent   Forum du club des développeurs et IT Pro > Bases de données > Firebird > SQL
SQL Forum d'entraide sur le SQL pour Firebird
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 06/08/2012, 19h50   #1
rv2931
Invité de passage
 
Inscription : février 2008
Messages : 9
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 9
Points : 0
Points : 0
Par défaut optimisation "UPDATE <> WHERE ID IN (SELECT <> )"

Bonjour,
J'utilise pas mal de requête du genre :
Code :
1
2
3
4
5
6
7
8
9
10
UPDATE MATABLE1 T1
SET T1.FIELD = "QQC"
WHERE T1.ID IN
(
SELECT T2.ID
FROM MATABLE1 T2
JOIN MATABLE2 T3
ON T2.ID = T3.T2ID
WHERE <conditions plus ou moins complexe...>
)
En fait, de souvenir, je passe par là car je suis en Firebird 2.1 et le moteur n'accepte pas de faire des UPDATE sur plusieurs tables:
Code :
1
2
3
UPDATE MATBLE1 T1,MATABLE2 T2
SET T1.FIELD = "QQC"
WHERE T1.F1 =... AND T2.F3 = ....
Ou même en passant par des JOIN au niveau de l'UPDATE, il rejette la requête

Le truc c'est qu'en passant par une sous-requête et en faisant WHERE ID IN (liste ID résultat d'une requête)
J'ai l'impression, en fait vu les statistique du résultat, c'est pas qu'une impression, qu'il exécute la sous-requête autant de fois qu'elle ne contient de résultat. Du coup, le temps d'exécution est énorme et est proportionnel au nombre de resultat de sou-requête.
Actuellement j'arrive à optimiser manuellement en exécutant la sous-requête, en copiant les résultats en y insérant une virgule et j'exécute l'UPDATE avec la liste des ID copiés.
Code :
1
2
3
4
UPDATE MATABLE1 T1
SET T1.FIELD = "QQC"
WHERE T1.ID IN
(234234,46573,23545,24567,5674578,65463,245654,....)
Efficace, mais laborieux :o/

N'y a-t-il pas un autre moyen pour faire ce genre de chose ?
Merci d'avance

Hervé

[EDIT] oublié le IN dans WHERE
rv2931 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/08/2012, 20h26   #2
skuatamad
Expert Confirmé
 
Inscription : août 2008
Messages : 1 690
Détails du profil
Informations forums :
Inscription : août 2008
Messages : 1 690
Points : 2 813
Points : 2 813
Je l'écrirais plutôt comme ça, inutile de repasser sur matable1 :
Code :
1
2
3
4
5
6
7
8
UPDATE MATABLE1 T1
   SET T1.FIELD = 'QQC'
 WHERE EXISTS (SELECT 1
                 FROM MATABLE2 T3
                WHERE T1.ID = T3.T2ID
                  AND <conditions plus ou moins complexe...>
              )
   AND <autres conditions>
Sinon il est également possible d'utiliser MERGE en ne précisant que la clause WHEN MATCHED, surtout utile quand la nouvelle valeur (ici QQC) provient d'une requête sur la table matable2.

[EDIT] Au fait je ne connais pas firebird, la doc sur merge concerne la 2.5, je ne sais pas si le fonctionnement est identique en 2.1
skuatamad est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/08/2012, 11h07   #3
rv2931
Invité de passage
 
Inscription : février 2008
Messages : 9
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 9
Points : 0
Points : 0
Merci skuatamad
Je vais essayer ça.
Effectivement, tu fais bien de préciser, j'ai l'impression que Firebird est en évolution perpétuelle, à la mode JAVA, du coup, suivant les versions, il y a des choses disponibles, d'autres non, d'autres plus...
rv2931 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/08/2012, 11h10   #4
rv2931
Invité de passage
 
Inscription : février 2008
Messages : 9
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 9
Points : 0
Points : 0
Je ne vois pas très bien le fonctionnement du SELECT 1 ?
Tu pourrais expliciter ?
Merci
rv2931 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/08/2012, 13h37   #5
skuatamad
Expert Confirmé
 
Inscription : août 2008
Messages : 1 690
Détails du profil
Informations forums :
Inscription : août 2008
Messages : 1 690
Points : 2 813
Points : 2 813
Avec EXISTS il n'est pas nécessaire de sélectionner des colonnes dans la sous-requête : EXISTS and SINGULAR
Citation:
The EXISTS predicate returns true if the result set of the subselect contains at least one row. If it is empty, EXISTS returns false.
Moi j'utilise 1 dans la sous-requête, d'autres NULL ou 'X', ou encore * mais je n'aime pas * qui fait un appel au dictionnaire (en tout cas il me semble que c'est vrai sur Oracle).

Et puis 1 ou NULL montre bien que la logique n'est pas dans les colonnes sélectionnées mais dans la corrélation entre les 2 requêtes.

Sinon tu peux aussi utiliser IN :
Code :
1
2
3
4
UPDATE MATABLE1 T1
   SET T1.FIELD = 'QQC'
 WHERE T1.ID IN (SELECT T3.T2ID FROM MATABLE2 T3 WHERE <conditions plus ou moins complexe...>)
   AND <autres conditions>
skuatamad est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/08/2012, 13h48   #6
rv2931
Invité de passage
 
Inscription : février 2008
Messages : 9
Détails du profil
Informations forums :
Inscription : février 2008
Messages : 9
Points : 0
Points : 0
Alors, désolé, j'avais oublié le IN dans la première requête de mon post.
J'utilise actuellement la méthode du WHERE T1.ID IN(SELECT. . . )
Et c'est justement l'objet de mon post car cette méthode prend énormément de temps car il semble que le moteur Firebird exécute la sous-requête autant de fois que le nombre de résultat de cette sous-requête, enfin c'est une supposition.
Mais plus il y a de résultats, plus ça prend des plombe.
Je vais essayer ton autre solution.
rv2931 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 08h46.


 
 
 
 
Partenaires

Hébergement Web