2015-09-25 2 views
1

J'ai défini des tables PIÈCES, cataloguer et plist code suivant dans Mysql:requête Mysql produit résultat différent lorsqu'il est utilisé comme sous-requête

create table parts (
    PID int 
); 
create table catalog(
    SID varchar(3), 
    PID int 
); 
create table plist(
    PID int 
); 
insert into parts values (1),(2),(3), (4); 
insert into catalog values 
    ("A", 1), ("A", 2), ("A", 4), 
    ("B", 2), ("B", 3), ("B", 4), 
    ("C", 1), ("C", 4), 
    ("D", 2), ("D", 3); 
insert into plist values (2), (4); 

Je veux effectuer le catalogue opérateur de division relationnelle plist. L'opérateur de division relationnelle n'est pas disponible dans SQL. La mise en œuvre suivante fonctionne avec succès dans Oracle:

SELECT DISTINCT(SID) FROM CATALOG A WHERE NOT EXISTS 
    (SELECT PID FROM PLIST MINUS SELECT PID FROM CATALOG WHERE SID = A.SID); 

Maintenant, dans MYsql MOINS opérateur n'est pas disponible. La requête suivante implémente avec succès l'opération MINUS utilisée ci-dessus (avec une modification introduite pour tester indépendamment la requête) dans Mysql.

SELECT B.PID FROM PLIST LEFT JOIN 
    (SELECT PID FROM CATALOG WHERE SID = "C") B ON B.PID=PLIST.PID 
    WHERE B.PID IS NULL; 

Cependant, quand je l'utilise comme code ci-dessus pour mettre en œuvre l'sous_requête opérateur de division relation comme

SELECT DISTINCT(SID) FROM CATALOG WHERE NOT EXISTS 
    (SELECT B.PID FROM PLIST LEFT JOIN 
     (SELECT A.PID FROM CATALOG A WHERE A.SID = SID) B ON B.PID = PLIST.PID 
     WHERE B.PID IS NULL 
); 

Je ne reçois pas le résultat escompté. Le résultat attendu contient uniquement les valeurs SID "A" et "B". Cependant, le résultat produit par le code ci-dessus contient les quatre valeurs SID. Cela est étrange car lorsque testé de manière indépendante, la sous-requête produit des résultats corrects (vide dans le cas de SID égal à "A" ou "B" et non vide pour les deux autres valeurs de SID).

Je serai reconnaissant si ce comportement étrange est expliqué par quelqu'un dans ce forum.

Merci beaucoup d'avance.

+0

J'ai utilisé l'alias A pour la table CATALOG dans la requête interne, au lieu de l'utiliser pour la requête externe car Mysql n'a pas reconnu l'alias utilisé pour la requête externe. –

+0

Je suis également au courant d'une implémentation alternative de MINUS utilisant l'opération IN que je pourrais utiliser avec succès pour implémenter la division relationnelle dans Mysql. –

Répondre

0

Le comportement est expliqué comme suit:

La requête écrite par moi est erronée puisque dans la requête interne, il n'y a pas de différence entre A.SID et SID. Par conséquent, la condition aboutit toujours à VRAI.

Ainsi, ce qui est prévu comme sous-requête corrélée n'est pas vraiment le cas.

Cela explique pourquoi le résultat de la requête contient les quatre SID.

Cependant, comme il est dit dans mon premier commentaire, quand j'utilisé un alias pour la table dans la requête externe, et utilisé cet alias dans la requête interne comme indiqué ci-dessous

SELECT DISTINCT(SID) FROM CATALOG A WHERE NOT EXISTS 
    (SELECT B.PID FROM PLIST LEFT JOIN 
     (SELECT PID FROM CATALOG WHERE SID = A.SID) B ON B.PID = PLIST.PID 
     WHERE B.PID IS NULL 
); 

Je reçois l'erreur: colonne inconnue "A.SID" dans la clause where.

Je ne comprends pas pourquoi l'alias A n'est pas dans la portée de la sous-requête.