将IF EXISTS移动到WHERE子句

时间:2014-12-19 20:54:31

标签: sql sql-server performance query-optimization

在此示例查询中(针对设计不佳的供应商数据库):

DECLARE @OrderNo AS CHAR(8) = LEFT(@FullOrderNo,8)

IF EXISTS (SELECT 1 FROM Foo WHERE FullOrderNumber = @FullOrderNo)

    SELECT  Stuff
    FROM    Foo
    WHERE   X = 'Y'
            AND FullOrderNumber = @FullOrderNo

  ELSE

    SELECT  Stuff
    FROM    Foo
    WHERE   X = 'Y'
            AND OrderNumber = @OrderNo

由于SELECT和WHERE子句的第一部分是相同的,有没有办法安全地组合查询,同时确保首先检查FullOrderNumber匹配?我看到有no guarantees for WHERE clause evaluation order

1 个答案:

答案 0 :(得分:3)

您可以将其写为:

SELECT  Stuff
FROM    Foo
WHERE   X = 'Y' AND
        (FullOrderNumber = @FullOrderNo OR
         (NOT EXISTS (SELECT 1 FROM Foo WHERE FullOrderNumber = @FullOrderNo) and OrderNumber = @OrderNo) )

如果您只查找一行,可以使用order by进行优先排序:

SELECT  TOP (1) Stuff
FROM    Foo
WHERE   X = 'Y' AND
        (FullOrderNumber = @FullOrderNo OR OrderNumber = @OrderNo)
ORDER BY (CASE WHEN FullOrderNumber = @FullOrderNo THEN 1 ELSE 2 END)

实际上,即使有重复项,您也可以使用with ties

SELECT  TOP (1) WITH TIES Stuff
FROM    Foo
WHERE   X = 'Y' AND
        (FullOrderNumber = @FullOrderNo OR OrderNumber = @OrderNo)
ORDER BY (CASE WHEN FullOrderNumber = @FullOrderNo THEN 1 ELSE 2 END)