【问题标题】:SQL Server : With in Select in NOT INSQL Server : 在中选择而不在中
【发布时间】:2014-08-06 14:38:38
【问题描述】:

我对这段代码有疑问。 我的数据库中有树,我需要选择除节点和他的孩子、孙子等之外的所有节点。 我完成了 WITH 查询 - 它有效。我可以选择节点的所有大家庭。 但是当我尝试执行 SELECT ... WHERE id NOT ID (这是大家庭)时,我遇到了错误...

代码:

Select * from TALBE 
where id NOT IN
(
    WITH TempTable 
    AS
    (
        SELECT ...
        UNION ALL
        SELECT ...
    )
    Select id from TempTable;
);

或其他版本

Select * from TALBE 
where id NOT IN
(
    select id from
    (
        WITH TempTable 
        AS
        (
            SELECT ...
            UNION ALL
            SELECT ...
        )
        Select id from TempTable
    )
);

在这段代码中,我需要有前 2 行。这不是我的决定 - 必须拥有。

错误:

Msg 156, Level 15, State 1, Line 4

关键字“WITH”附近的语法不正确。

Msg 319, Level 15, State 1, Line 4

关键字“with”附近的语法不正确。如果这个语句是一个公用表表达式、一个 xmlnamespaces 子句或一个更改跟踪上下文子句,则前面的语句必须以分号结束。

Msg 102, Level 15, State 1, Line 14

')' 附近的语法不正确。

【问题讨论】:

  • 您不能将 cte 嵌套为子选择。去掉cte就行了,这里不需要。
  • AFAIK WITH 必须始终以; 开头(或者当然是您脚本中的第一个语句)-就像@SeanLange 提到的那样,不要尝试嵌套您的WITH变成别的东西

标签: sql sql-server with-statement


【解决方案1】:

正如 cmets 所建议的,您需要删除 CTE 或将其移至查询的开头。

http://technet.microsoft.com/en-us/library/ms190766(v=sql.105).aspx

WITH TempTable 
AS
(
     SELECT ...
     UNION ALL
     SELECT ...
)
Select * from TALBE 
where id NOT IN
(
    select id from TempTable
);

【讨论】:

    【解决方案2】:

    按照这段代码的编写方式,CTE 查询将针对您正在测试的每一行运行,因为 CTE 并不是真正的结果集,而是一条语句。这很可能会导致性能问题。更好的方法是将查询结果缓存在内存中的表中,并在进行实际选择时使用它们,如下所示:

    DECLARE @badIds TABLE
    (
        Id INT NOT NULL --replace the INT with whatever type your Id column is
    )
    
    INSERT INTO @badIds
    SELECT someId
    FROM someTable
    UNION ALL
    SELECT someOtherId
    FROM someOtherTable
    ...
    
    SELECT * FROM Table WHERE id NOT IN (SELECT Id FROM @badIds)
    

    【讨论】:

      【解决方案3】:

      类似的东西。您可能应该阅读有关 CTE 的文档,以便了解它们是什么以及如何使用它们。

      Select * from TALBE 
      where id NOT IN
      (
          SELECT ID from someTable
          UNION ALL
          SELECT ID from SomeOtherTable
      );
      

      现在听起来您希望将此作为递归 cte,您需要稍微调整一下。

      WITH TempTable 
      AS
      (
          SELECT ...
          UNION ALL
          SELECT ...
      )
      
      Select * from TALBE 
      where id NOT IN
      (
          SELECT ID from TempTable
      );
      

      【讨论】:

      • 这个只处理两层,不是n层,不是递归的。
      • 您最初发布的内容似乎也不是递归的。如果您需要递归 cte,请将其移到查询之外。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多