sql - T-SQL 条件 WHERE 子句

标签 sql sql-server tsql where-clause case-statement

在这里发现了几个类似的问题,但无法弄清楚如何应用于我的场景。

我的函数有一个名为@IncludeBelow的参数。值为 0 或 1 (BIT)。

我有这个查询:

SELECT p.*
FROM Locations l
INNER JOIN Posts p
on l.LocationId = p.LocationId
WHERE l.Condition1 = @Value1
AND   l.SomeOtherCondition = @SomeOtherValue

如果@IncludeBelow为0,我需要的查询是这样的:

SELECT p.*
FROM Locations l
INNER JOIN Posts p
on l.LocationId = p.LocationId
WHERE l.Condition1 = @Value1
AND   l.SomeOtherCondition = @SomeOtherValue
AND   p.LocationType = @LocationType -- additional filter to only include level.

如果 @IncludeBelow 为 1,则需要排除最后一行。 (即不应用过滤器)。

我猜它需要是一个 CASE 语句,但无法弄清楚语法。

这是我尝试过的:

SELECT p.*
FROM Locations l
INNER JOIN Posts p
on l.LocationId = p.LocationId
WHERE l.Condition1 = @Value1
AND   l.SomeOtherCondition = @SomeOtherValue
AND (CASE @IncludeBelow WHEN 0 THEN p.LocationTypeId = @LocationType ELSE 1 = 1)

显然这是不正确的。

正确的语法是什么?

最佳答案

我将查询更改为使用 EXISTS,因为如果有多个位置与 POST 关联,则会出现重复的 POST 记录,需要使用 DISTINCT 或 GROUP BY 子句来删除...

不可控制的

这将执行最差的可能解决方案:

SELECT p.*
  FROM POSTS p
 WHERE EXISTS(SELECT NULL
                FROM LOCATIONS l
               WHERE l.LocationId = p.LocationId
                 AND l.Condition1 = @Value1
                 AND l.SomeOtherCondition = @SomeOtherValue)
   AND (@IncludeBelow = 1 OR p.LocationTypeId = @LocationType)

可控制的非动态版本

不言自明......

BEGIN
  IF @IncludeBelow = 0 THEN
    SELECT p.*
      FROM POSTS p
     WHERE EXISTS(SELECT NULL
                    FROM LOCATIONS l
                   WHERE l.LocationId = p.LocationId
                     AND l.Condition1 = @Value1
                     AND l.SomeOtherCondition = @SomeOtherValue)
       AND p.LocationTypeId = @LocationType
  ELSE
    SELECT p.*
      FROM POSTS p
     WHERE EXISTS(SELECT NULL
                    FROM LOCATIONS l
                   WHERE l.LocationId = p.LocationId
                     AND l.Condition1 = @Value1
                     AND l.SomeOtherCondition = @SomeOtherValue) 
END

可控制的动态版本 (SQL Server 2005+):

喜欢或讨厌它,动态 SQL 让您只需编写一次查询即可。请注意,sp_executesql 会缓存查询计划,这与 SQL Server 中的 EXEC 不同。强烈推荐阅读The Curse and Blessings of Dynamic SQL在考虑 SQL Server 上的动态 SQL 之前...

DECLARE @SQL VARCHAR(MAX)
    SET @SQL = 'SELECT p.*
                  FROM POSTS p
                 WHERE EXISTS(SELECT NULL
                                FROM LOCATIONS l
                               WHERE l.LocationId = p.LocationId
                                 AND l.Condition1 = @Value1
                                 AND l.SomeOtherCondition = @SomeOtherValue)'

    SET @SQL = @SQL + CASE 
                        WHEN @IncludeBelow = 0 THEN
                         ' AND p.LocationTypeId = @LocationType '
                        ELSE ''
                      END   

BEGIN 

  EXEC sp_executesql @SQL, 
                     N'@Value1 INT, @SomeOtherValue VARCHAR(40), @LocationType INT',
                     @Value1, @SomeOtherValue, @LocationType

END

关于sql - T-SQL 条件 WHERE 子句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4485965/

相关文章:

sql - 数据库设计完整性检查

sql - SQL中如何优雅地比较同一个表中的值

sql-server - 为什么SELECT可以有SIU锁(SQL Server 2012)?

c# - SQL 日期问题 : How to get Yesterdays date in the following formatte

sql - Oracle SELECT - 一列的别名作为另一列的输入

sql - DB2 选择不等于 NULL 的字符串

php - SQL 或 PHP 中的自动十进制数字格式?

sql - 在 SQL Server 中使用带有 IN 子句的 uniqueidentifier

mysql - Microsoft SQL Server 相当于此 MySQL 查询

sql - T-SQL 过程 - 将参数过滤为 Object/CLR/Xml/UDT