SQL 服务器 - 相关子查询/自连接

SQL Server - Correlated Subqueries / Self Join

一个 select 声明 return 位于唯一城市和州的每个供应商的名称、城市和州(即,排除与另一个供应商具有相同城市和州的供应商)

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;

备选答案

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;

我理解第一个答案,但不理解备用查询。混淆点:return 0 行下面的行不是因为它们引用相同的 table 而没有附加的 where 子句吗?

WHERE Vendors_Sub.VendorID <> Vendors_Main.VendorID)
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;

子查询

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

将 return 主查询中每一行的 vendorCity + vendorState 的所有现有组合,不包括具有相同 ID 的行。将子查询想象成为主查询中的每一行调用的函数。

如果 WHERE Vendors_Sub.VendorID <> Vendors_Main.VendorID 不存在,每个主查询行将在子查询中与自身匹配,并且整个查询将 return 没有行,因为 none 组合将是唯一的。

WHERE Vendors_Sub.VendorID <> Vendors_Main.VendorID) 不比较相同 table.

的同一行

一个相关子查询在逻辑上对外部查询中的每一行执行一次,在你的例子中它检查具有相同VendorCity/[=13=的行]组合,但不同VendorIDs.

事实上我更喜欢直接翻译成相关的 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;

这可以防止像 'state' + 'acity''statea' + 'city' 这样的误报,它们都连接到 'stateacity' 并且适用于任何类型的数据类型。