如何在WHERE子句中模拟COALESCE条件

时间:2014-01-09 21:49:29

标签: sql-server tsql sql-server-2012

说我有以下内容:

SELECT    * 

FROM      Xyz 

WHERE     (@a IS NULL OR a = @a) AND
          (@b IS NULL OR b = @b) AND
          (@c IS NULL OR c = @c)

我想要完成的是更改WHERE子句以使用COALESCE方式的条件,它将使用非空的第一个条件或条件用完。

在伪说话中它会是这样的:

WHERE    IF @a IS NOT NULL THEN
         (
             a = @a
         )
         ELSE IF @b IS NOT NULL THEN 
         (
             b = @b
         )
         ELSE IF @c IS NOT NULL THEN 
         (
             c = @c
         )

这可能吗?

4 个答案:

答案 0 :(得分:4)

可能有更优雅的方式,但这应该尊重所需的逻辑

where
(@a is not null and @a = a) or
(@a is null and @b is not null and @b = b) or
(@a is null and @b is null and @c is not null and @c = c)

可以(有点)简化为:

where
(@a = a) or
(@a is null and @b = b) or
(@a is null and @b is null and @c = c)

答案 1 :(得分:4)

这会将NULL视为通配符:

SELECT *
FROM MyTable
WHERE COALESCE(
  NULLIF(@a,a),
  NULLIF(@b,b),
  NULLIF(@c,c)
) IS NULL

这将使用第一个非空条件:

SELECT *
FROM MyTable
WHERE EXISTS (
  SELECT id,value
  FROM (VALUES (1,a),(2,b),(3,c)) t1(id,value)
  INTERSECT
  SELECT TOP 1 id,comparator
  FROM (VALUES (1,@a),(2,@b),(3,@c)) t(id,comparator)
  WHERE comparator IS NOT NULL
  ORDER BY id
)

答案 2 :(得分:3)

/* 
Since you are dynamically changing your condition you will need to 
use Dynamic sql and and build your query dynamically something like
this......
*/

CREATE TABLE Test_Dynamic (ID INT, A INT, B INT, C INT)
INSERT INTO Test_Dynamic VALUES
(1, 100, 1000, 10000),
(2, 200, 2000, 20000),
(3, 300, 3000, 30000),
(4, 400, 4000, 40000)

DECLARE @a INT, @b INT, @c INT;
SET @a = 100;
--SET @b = 1000;
--SET @c = 10000;

DECLARE @Sql NVARCHAR(MAX);

SET @Sql = N'SELECT * FROM  Test_Dynamic  WHERE 1 = 1 '

IF (@a IS NOT NULL)
BEGIN
 SET @Sql = @Sql + N' AND A = @ar'
  IF (@b IS NOT NULL)
    BEGIN
     SET @Sql = @Sql + N' AND B = @br'
       IF (@c IS NOT NULL)
         BEGIN
         SET @Sql = @Sql + N' AND C = @cr'
         END   
    END
END

PRINT @Sql

EXECUTE sp_executesql @Sql
                      ,N'@ar INT, @br INT, @cr INT'
                      ,@ar = @a
                      ,@br = @b
                      ,@cr = @c

答案 3 :(得分:3)

您不能将布尔表达式的结果用作SQL Server中的值,但您可以将其替换为逻辑1 / 0,如下所示:

WHERE
  CASE
              WHEN @a IS NOT NULL AND a = @a THEN 1
    ELSE CASE WHEN @b IS NOT NULL AND b = @b THEN 1
    ELSE CASE WHEN @c IS NOT NULL AND c = @c THEN 1
  END END END = 1

以上也可以像这样重新排列(也许有些人会发现逻辑更加清晰):

WHERE
  CASE
    WHEN @a IS NOT NULL AND a = @a THEN 1
    ELSE
      CASE
        WHEN @b IS NOT NULL AND b = @b THEN 1
        ELSE
          CASE
            WHEN @c IS NOT NULL AND c = @c THEN 1
          END
      END
  END = 1