2017-01-24 3 views
0

Je me demande, si la sous-requête dans l'instruction de mise à jour suivante est bonne (non corrélée) ou mauvaise (sous-requête)? En d'autres termes, ma question est la suivante: est-ce une requête inefficace?Sous-requête incorrecte (corrélée) ou bonne (non corrélée)?

UPDATE tableA 
SET field1=0 
FROM tableA 
WHERE field2 IN (SELECT field2 
       FROM tableA 
       WHERE someField IS NOT NULL 
       AND someOtherField = 'ABC') 
+4

Il n'y a pas de règle comme "bon (non corrélé) ou mauvais (sous-requête) "! – jarlh

+4

Et il n'est pas corrélé - c'est juste une sous-requête –

+0

Une sous-requête corrélée inclut une condition avec une référence à la requête principale. – jarlh

Répondre

0

Les sous-requêtes ne sont pas intrinsèquement bon ou mauvais (on pourrait dire plutôt que optimiseurs SQL sont mauvaises, plutôt que sous-requêtes). Votre exemple n'est pas corrélé du tout.

La question de savoir si une requête particulière est efficace ou non nécessite l'analyse du plan d'exécution. Cela, à son tour, dépend principalement de la distribution des données, des index et des schémas de partitionnement des données. Il n'y a rien a priori mauvais à propos de votre requête.

Il existe d'autres façons d'écrire la logique. J'aime celui-ci:

WITH toupdate as (
     SELECT a.*, 
      SUM(CASE WHEN someField IS NOT NULL AND someOtherField = 'ABC' 
         THEN 1 ELSE 0 
       END) OVER (PARTITION BY field2) as cnt 
     FROM tableA a 
    ) 
UPDATE toupdate 
    SET field1 = 0 
    WHERE cnt > 0; 

Ce n'est pas 100% identique. Une différence est que cela traite une valeur NULL dans field2 comme toute autre valeur; votre version ne mettra jamais à jour une valeur NULL.

+0

* votre version ne mettra jamais à jour une valeur NULL. * => Quelle valeur NULL ne sera pas mise à jour? – beta

+0

Une ligne où 'field2' est' NULL' ne sera jamais mise à jour. –

1

Votre requête n'est pas corrélée, juste un sous-requête ..

ci-dessous est une sous-requête corrélée ..

UPDATE a 
SET field1=0 
FROM tableA a 
WHERE exists (SELECT 1 
       FROM tableB b 
       WHERE a.somecol=b.somecol) 

un exemple de sous-requête corrélée

select orderid, 
(select custname from customers c where c.custid=o.custid) from orders o 

ci-dessus requête peut être écrit comme jointure

select orderid,custname 
from orders o 
join 
customers c 
on c.custid=o.custid 

exécuter les deux requêtes ont tendance à utiliser le même plan d'exécution et les deux ont même coût que well..so nous ne pouvons supposer, ne Corrélés les sous-requêtes de meilleures performances

enter image description here

select orderid, 
(select count(orderid) from orders o2 where o2.custid=o.custid) 
from orders o 

pour ce qui précède corrélés sous-requête, SQL ne peut pas accéder à la table des ordres une seule fois et faire tous les calculs, il devra accéder à la table deux fois ... c'est seulement gotcha je pourrais voir avec sous-requêtes corrélées