2015-10-14 3 views
0

Une instruction select renvoyant le nom, la ville et l'état de chaque fournisseur situé dans une ville et un état uniques (excluant les fournisseurs ayant la même ville et l'état avec un autre fournisseur)SQL Server - Sous-requêtes corrélées/auto-joint

SELECT 
    VendorName, VendorCity, VendorState 
FROM 
    Vendors 
WHERE 
    VendorState + VendorCity NOT IN (SELECT VendorState + VendorCity 
            FROM Vendors 
            GROUP BY VendorState + VendorCity 
            HAVING COUNT(*) > 1) 
ORDER BY 
    VendorState, VendorCity; 

réponse autre

SELECT 
    VendorName, VendorCity, VendorState 
FROM 
    Vendors AS Vendors_Main 
WHERE 
    VendorCity + VendorState NOT IN (SELECT VendorCity + VendorState 
            FROM Vendors AS Vendors_Sub 
            WHERE Vendors_Sub.VendorID <> Vendors_Main.VendorID) 
ORDER BY 
    VendorState, VendorCity; 

Je comprends la première réponse, mais pas la requête alternative. Point de confusion: la ligne ci-dessous ne renvoie-t-elle pas 0 lignes puisqu'elles référencent la même table sans clause where supplémentaire?

WHERE Vendors_Sub.VendorID <> Vendors_Main.VendorID) 

Répondre

0

WHERE Vendors_Sub.VendorID <> Vendors_Main.VendorID) ne compare pas la même ligne de la même table.

Une sous-requête corrélée est logiquement exécutée une fois pour chaque ligne de la requête externe, dans votre cas, il vérifie les lignes avec la même combinaison VendorCity/VendorState, mais différent VendorIDs.

En fait, je préférerais une traduction directe en corrélation NOT EXISTS:

SELECT VendorName, VendorCity, VendorState 
FROM Vendors AS Vendors_Main 
WHERE NOT EXISTS 
(
    SELECT * 
    FROM Vendors AS Vendors_Sub 
    WHERE Vendors_Sub.VendorCity = Vendors_Main.VendorCity -- same city 
    AND Vendors_Sub.VendorState = Vendors_Main.VendorState -- same state 
    AND Vendors_Sub.VendorID <> Vendors_Main.VendorID -- different vendor 
) 
ORDER BY VendorState, VendorCity; 

Cela évite les faux positifs comme 'state' + 'acity' par rapport 'statea' + 'city' tous deux à concaténer 'stateacity' et fonctionne pour tout type de type de données.

0
SELECT VendorName , 
     VendorCity , 
     VendorState 
FROM Vendors AS Vendors_Main 
WHERE VendorCity + VendorState NOT IN 
    (
     SELECT VendorCity + VendorState 
     FROM Vendors AS Vendors_Sub 
     WHERE Vendors_Sub.VendorID <> Vendors_Main.VendorID 
    ) 
ORDER BY VendorState ,VendorCity; 

La sous requête

SELECT VendorCity + VendorState 
FROM Vendors AS Vendors_Sub 
WHERE Vendors_Sub.VendorID <> Vendors_Main.VendorID 

retournera toutes les combinaisons existantes de vendorCity + vendorState pour chaque ligne de la requête principale exclusion de ceux avec le même identifiant. Imaginons la sous-requête en tant que fonction appelée pour chaque ligne de la requête principale.

Si WHERE Vendors_Sub.VendorID <> Vendors_Main.VendorID n'était pas présent, chaque ligne de requête principale correspondrait à elle-même dans la sous-requête et la requête entière ne retournerait aucune ligne car aucune des combinaisons ne serait unique.