SQL Server 2014 中的相关子查询

MSI*_*SIS 4 sql-server subquery

我正在运行一个相关的子查询来找出不同城市、州的供应商列表(按供应商名称),即我们想知道与其他供应商没有共同城市和州的供应商。似乎可以自行加入。

如果可能,请仅提供提示。

供应商表是:

Vendors(VendorID P, VendorCity, VendorState, VendorName,...)
Run Code Online (Sandbox Code Playgroud)

这就是我所拥有的:

Select VendorName, VendorCity, VendorState from Vendors AS V1 where
         VendorCity, VendorState NOT IN (Select VendorCity, VendorState FROM
          Vendors AS V2 where V2.VendorID <> V1.VendorID)
Run Code Online (Sandbox Code Playgroud)

这是我收到的错误消息:

消息 4145,级别 15,状态 1,第 2 行 在“,”附近的预期条件的上下文中指定的非布尔类型的表达式。

我不明白为什么要引用布尔类型,因为这不是 EXISTS 或其他相关查询。

Jul*_*eur 6

IN(...)的语法是:

test_expression [ NOT ] IN 
    ( subquery | expression [ ,...n ]    ) 
Run Code Online (Sandbox Code Playgroud)

和:

测试表达式

是任何有效的表达式。

子查询

具有一列结果集的子查询。此列必须与 test_expression 具有相同的数据类型。

表达式[ ,... n ]

是要测试匹配的表达式列表。所有表达式的类型必须与 test_expression 相同。

这意味着两侧只允许有 1 列。甚至表达式列表也被视为 1 个虚拟表,其中包含 1 列的表达式值,类似于:

SELECT exp FROM (values(exp1), (exp2), ...) as X(exp)
Run Code Online (Sandbox Code Playgroud)

对于 2 列,您可以将子查询与EXISTS 一起使用

Select VendorName, VendorCity, VendorState 
FROM Vendors AS V1 
WHERE NOT EXISTS (
    SELECT 1 
    FROM Vendors AS V2 
    WHERE V2.VendorID <> V1.VendorID
        AND VendorCity = VendorCity
        AND VendorState = VendorState
)
Run Code Online (Sandbox Code Playgroud)

总的来说,这个子查询总是返回 0 行或 1 行或更多行,因为它只需要知道是否有 1 行或更多行具有相同的城市和州。该值并不重要,因为它只查看行数(=> 如果 1 行或更多行存在),因此SELECT 1. 测试已经在内部WHERE子句中完成了。

我猜 VendorId 是 PK。VendorCity 和 VendorState 的索引会有所帮助。

既然你在学习,如果你还不知道,你也可以看看APPLY的用法(CROSS APPLYOUTER APPLY)。我让你试一试。


Mar*_*ith 5

另一个答案中所述,SQL Server 目前不允许您想要的语法。其他产品可以,这里有一个 Connect 项目请求:

添加对 ANSI 标准行值构造函数的支持

NOT IN虽然仍然可以使用

SELECT VendorName,
       VendorCity,
       VendorState
FROM   Vendors AS V1
WHERE  1 NOT IN (SELECT 1
                 FROM   Vendors AS V2
                 WHERE  V2.VendorCity = V1.VendorCity
                        AND V2.VendorState = V1.VendorState
                        AND V2.VendorID <> V1.VendorID);
Run Code Online (Sandbox Code Playgroud)

这给出了一个类似的计划,带有反半连接运算符,如 NOT EXISTS