Tsql 当子查询没有引入EXISTS时,如何在select列表中指定两个表达式

Tsql 当子查询没有引入EXISTS时,如何在select列表中指定两个表达式,tsql,sql-server-2012-express,Tsql,Sql Server 2012 Express,我有一个使用子查询的查询,返回预期结果时遇到问题。我收到的错误是…“当子查询没有引入EXISTS时,只能在选择列表中指定一个表达式。”我如何重写该表达式才能工作 SELECT a.Part, b.Location, b.LeadTime FROM dbo.Parts a LEFT OUTER JOIN dbo.Vendor b ON b.Part = a.Part WHERE b.Location IN ('A','B','C') AND

我有一个使用子查询的查询,返回预期结果时遇到问题。我收到的错误是…“当子查询没有引入EXISTS时,只能在选择列表中指定一个表达式。”我如何重写该表达式才能工作

SELECT
    a.Part,
    b.Location,
    b.LeadTime
FROM
    dbo.Parts a
    LEFT OUTER JOIN dbo.Vendor b ON b.Part = a.Part
WHERE
    b.Location IN ('A','B','C')
AND
    Date IN (SELECT Location, MAX(Date) FROM dbo.Vendor GROUP BY Location)
GROUP BY
    a.Part,
    b.Location,
    b.LeadTime
ORDER BY
    a.Part

在子查询中,需要将位置和零件与外部查询关联起来。 例如:

Date = (SELECT MAX(Date) 
        FROM dbo.Vender v 
        WHERE v.Location = b.Location 
          AND v.Part = b.Part
       )

因此,这将为子查询中的每个位置和部分返回一个日期,您需要将位置和部分与外部查询关联起来。 例如:

Date = (SELECT MAX(Date) 
        FROM dbo.Vender v 
        WHERE v.Location = b.Location 
          AND v.Part = b.Part
       )

因此,这将为每个位置和零件返回一个日期

如果我正确理解您的意思,您希望位置A、B和C的行具有最大日期。现在,假设SQL Server 2005+,您可以执行以下操作:

;WITH CTE AS
(
    SELECT
        a.Part,
        b.Location,
        b.LeadTime,
        RN = ROW_NUMBER() OVER(PARTITION BY a.Part ORDER BY [Date] DESC)
    FROM
        dbo.Parts a
        LEFT OUTER JOIN dbo.Vendor b ON b.Part = a.Part
    WHERE
        b.Location IN ('A','B','C')
)
SELECT  Part, 
        Location,
        LeadTime
FROM CTE
WHERE RN = 1
ORDER BY Part

如果我正确理解了您的意思,那么您希望位置A、B和C的行具有最大日期。现在,假设SQL Server 2005+,您可以执行以下操作:

;WITH CTE AS
(
    SELECT
        a.Part,
        b.Location,
        b.LeadTime,
        RN = ROW_NUMBER() OVER(PARTITION BY a.Part ORDER BY [Date] DESC)
    FROM
        dbo.Parts a
        LEFT OUTER JOIN dbo.Vendor b ON b.Part = a.Part
    WHERE
        b.Location IN ('A','B','C')
)
SELECT  Part, 
        Location,
        LeadTime
FROM CTE
WHERE RN = 1
ORDER BY Part

我想这可能就是你想要的。您没有说明SQL Server的哪个版本--这在SQL 2005及更高版本中有效:

SELECT
    p.Part,
    p.Location, -- from *p*, otherwise if no match we'll get a NULL
    v.LeadTime
FROM
    dbo.Parts p
    OUTER APPLY (
       SELECT TOP (1) * -- * here is okay because we specify columns outside
       FROM dbo.Vendor v
       WHERE p.Location = v.Location -- the correlation part
       ORDER BY v.Date DESC
    ) v
WHERE
    p.Location IN ('A','B','C')
ORDER BY
    p.Part
;
现在,可以通过添加“correlation”部分将查询更改为
相关子查询来修复查询,如中所示(还可以删除
GROUP by
子句)。但是,该方法仍然需要额外的、不必要的连接,这会影响性能,而且一次只能拉一列。此方法允许您从另一个表中提取所有列,并且没有额外的联接

注意:这在逻辑上给出了与相同的结果,但出于以下几个原因,我更喜欢它:

  • 当相关列(
    位置
    ,此处)上有索引时,搜索可以满足这一要求,但
    行号
    解决方案必须扫描(我相信)
  • 我更喜欢这种更直接、简洁地表达查询意图的方式。在
    Row\u Number
    方法中,必须进入外部条件,查看我们仅获取
    rn=1
    值,然后返回到CTE中,查看这是什么
  • 使用
    交叉应用
    外部应用
    ,每个外部行选择的单个内部行中未涉及的所有其他表都位于(对我而言)它们所属的位置之外。我们不是在一起解决问题。使用
    Row\u Number
    感觉有点像在查询上抛出一个
    DISTINCT
    来修复重复,而不是处理底层问题。我想这基本上是同一个问题,因为前面的观点用了不同的措辞
  • 当您有两个表要从中提取最新的值时,
    行编号()
    解决方案就会完全崩溃。使用这种语法,您只需简单地添加另一个
    APPLY
    子句,您所做的事情就一目了然了。对于多表场景,有一种方法可以通过将其他表移到外部来使用
    Row\u Number
    ,但我仍然不喜欢这种语法
  • 使用此语法,您可以根据所选行是否存在(在未找到匹配行的情况下)执行其他联接。在
    Row\u Number
    解决方案中,您只能合理地在外部查询中执行
    notnull
    检查——因此,您必须将查询拆分为多个独立的部分(您不希望加入将要丢弃的值!)

  • 另外,我强烈建议你使用别名来暗示他们所代表的表格。请不要使用
    a
    b
    。我将
    p
    用于
    零件
    v
    用于
    供应商
    ——这有助于您和其他人在将来更快地理解查询。

    我想这可能是您正在寻找的东西。您没有说明SQL Server的哪个版本--这在SQL 2005及更高版本中有效:

    SELECT
        p.Part,
        p.Location, -- from *p*, otherwise if no match we'll get a NULL
        v.LeadTime
    FROM
        dbo.Parts p
        OUTER APPLY (
           SELECT TOP (1) * -- * here is okay because we specify columns outside
           FROM dbo.Vendor v
           WHERE p.Location = v.Location -- the correlation part
           ORDER BY v.Date DESC
        ) v
    WHERE
        p.Location IN ('A','B','C')
    ORDER BY
        p.Part
    ;
    
    现在,可以通过添加“correlation”部分将查询更改为
    相关子查询来修复查询,如中所示(还可以删除
    GROUP by
    子句)。但是,该方法仍然需要额外的、不必要的连接,这会影响性能,而且一次只能拉一列。此方法允许您从另一个表中提取所有列,并且没有额外的联接

    注意:这在逻辑上给出了与相同的结果,但出于以下几个原因,我更喜欢它:

  • 当相关列(
    位置
    ,此处)上有索引时,搜索可以满足这一要求,但
    行号
    解决方案必须扫描(我相信)
  • 我更喜欢这种更直接、简洁地表达查询意图的方式。在
    Row\u Number
    方法中,必须进入外部条件,查看我们仅获取
    rn=1
    值,然后返回到CTE中,查看这是什么
  • 使用
    交叉应用
    外部应用
    ,每个外部行选择的单个内部行中未涉及的所有其他表都位于(对我而言)它们所属的位置之外。我们不是在一起解决问题。使用
    Row\u Number
    感觉有点像在查询上抛出一个
    DISTINCT
    来修复重复,而不是处理底层问题。我想这基本上是同一个问题,因为前面的观点用了不同的措辞
  • 当您有两个表要从中提取最新的值时,
    行编号()
    解决方案就会完全崩溃。使用这种语法,您只需简单地添加另一个
    APPLY
    子句,您所做的事情就一目了然了。对于多表场景,有一种方法可以通过将其他表移到外部来使用
    Row\u Number
    ,但我仍然不喜欢这种语法
  • 使用此语法,您可以根据所选行是否存在(在未找到匹配行的情况下)执行其他联接。在
    行中\u编号<