代码之家  ›  专栏  ›  技术社区  ›  Marc

sql where子句中的条件运算符

  •  7
  • Marc  · 技术社区  · 15 年前

    我希望我可以在sql server 2005中对where子句执行如下操作(我知道这是无效的)。有时@teamid(传递到存储过程中)将是现有teamid的值,否则它将始终为零,我需要team表中的所有行。

    我研究了usecase,运算符需要在整个语句之前或之后出现,这使得我无法根据@teamid的值使用不同的运算符。除了复制我的select语句之外的任何建议。

        declare @teamid int
        set @teamid = 0
    
        Select Team.teamID From Team
          case @teamid
             when 0 then 
                WHERE Team.teamID > 0
             else
                WHERE Team.teamID = @teamid
          end 
    
    5 回复  |  直到 15 年前
        1
  •  19
  •   Andomar    15 年前

    你可以在没有案子的情况下这样做:

    SELECT  Team.teamID 
    FROM    Team
    WHERE   (@teamid = 0 AND Team.teamID > 0)
            OR (@teamid <> 0 AND Team.teamID = @teamid)
    
        2
  •  5
  •   OMG Ponies    15 年前

    如果不使用动态SQL,最有效的选项是:

    IF @teamid = 0
      BEGIN
    
        SELECT t.teamid
          FROM TEAM t
         WHERE t.teamid > 0
    
      END
    ELSE
      BEGIN
    
        SELECT t.teamid
          FROM TEAM t
         WHERE t.teamid = @teamid
    
      END
    

    使用动态SQL:

    DECLARE @SQL NVARCHAR(4000)
       SET @SQL = 'SELECT t.teamid
                     FROM TEAM t
                    WHERE 1 = 1 '
    
       SET @SQL = @SQL + CASE @teamid
                           WHEN 0 THEN ' AND t.teamid > 0 '
                           ELSE ' AND t.teamid = @teamid '
                         END
    
    BEGIN
    
      EXEC sp_EXECUTESQL @SQL N'@teamid INT', @teamid
    
    END
    

    当心 sp_EXECUTESQL 缓存查询计划,而exec不会。阅读此: http://www.sommarskog.se/dynamic_sql.html

        3
  •  2
  •   Program.X    15 年前

    如何:

    Select Team.teamID From Team Where (@teamid=0 and team.teamID>0) or (@teamid<>0 and team.teamid=@teamid)
    
        4
  •  2
  •   tpdi    15 年前

    甚至比andomar的答案更简单,并且假设id永远不是0(对于大多数自动递增id来说)

    SELECT  Team.teamID 
    FROM    Team
    WHERE   @teamid = 0 or Team.teamID = @teamid;
    

    当@teamid为零时,该谓词始终为true,否则仅当它与特定行的teamid匹配时才为true。

    不过,请注意:这在Sybase 11或更高版本上非常有效;在MS SQL Server 2003上非常无效;我不知道它在当前版本的MS SQL Server上是如何工作的。

    另外,您可以使用case;您只需将case放在where子句中,而不是放在case中的where子句中。所以你最初的问题是:

    Select Team.teamID 
    From Team
    where 
       case when @teamid = 0 then 0 else Team.teamID end = @teamId;
    

    不过,请注意,这可能效率较低,因为必须对每行进行评估,而且还可能导致全表扫描。

    我上面给出的表单更有可能被智能查询优化器重写(您的里程数取决于您的rdbms),以便在@teamid不为零时使用索引。

        5
  •  0
  •   JeffO    15 年前

    如果可以将空视为所有记录:

    WHERE Team.teamID = ISNULL(@teamid, Team.teamID)