Предопределена ли последовательность проверок условий в предложении WHERE? - PullRequest
2 голосов
/ 05 июня 2009

Пример:

SELECT *
FROM [User]
WHERE [Value1] > 0
AND [Value2] / [Value1] > 3

Я бы хотел избежать ситуации деления на ноль. Могу ли я быть уверен, что первое условие будет проверено первым, а второе никогда не получит удар, если первое условие ложно? Я предполагаю, что планировщику запросов разрешено переставлять последовательность, если это приведет к большей производительности.

Ответы [ 6 ]

4 голосов
/ 05 июня 2009
SELECT  *
FROM    [User]
WHERE   CASE WHEN Value1 = 0 THEN 0 ELSE [Value2] / [Value1]  END > 3

или даже лучше:

SELECT  *
FROM    [User]
WHERE   [Value2] / NULLIF([Value1], 0) > 3

Деление на NULL всегда безопасно.

Обратите внимание, что если в вашей таблице много [Value1] = 0 и индекс [Value1], то следующий запрос:

SELECT  *
FROM    [User]
WHERE   [Value1] > 0
        AND [Value2] / NULLIF([Value1], 0) > 3

, будет использовать индекс и просто пропустить неправильные значения.

На это, однако, не следует полагаться, и NULLIF все равно следует использовать. Во всяком случае, это почти бесплатно.

0 голосов
/ 05 июня 2009

Вы не можете рассчитывать на сервер, обрабатывающий ваши условия в указанном порядке. Обычно оптимизатор запускает их в любом порядке, который он считает быстрее . Обычно то, что вы перечислили, должно быть безопасным, но я видел крайние случаи, когда оптимизатор запутывается.

Один хороший способ сделать оптимизатор таким, чтобы условие [Value1] > 0 было быстрее, - это иметь индекс для Value1, но не для Value2.

0 голосов
/ 05 июня 2009

Хорошо для начала ...

Value1 / Value1 == 1 //always...

но при условии, что это другой столбец.

SELECT top 20 * from [User]
WHERE
CASE WHEN Value2 > 0
    THEN convert(decimal(18,2), Value1) / convert(decimal(18,2), Value2) 
    ELSE 0
END > 3 
0 голосов
/ 05 июня 2009

Ваш оригинальный код SQL будет отлично работать:)

0 голосов
/ 05 июня 2009

Обычно нет. Оптимизатор находит лучший способ выполнить запрос.

SQL не дает явного кода: это просто инструкция для оптимизатора возвращать данные в определенных форматах, заказах, отфильтрованных и т. Д.

SELECT *
FROM [User]
WHERE [Value1] > 0
AND [Value1] / [Value1] > 3

--could be this
SELECT *
FROM
    (SELECT *
    FROM [User]
    WHERE [Value1] > 0
) foo
WHERE [Value1] / [Value1] > 3

--but to be safe
SELECT *
FROM
    (SELECT TOP 2000000000 *
    FROM [User]
    WHERE [Value1] > 0
    ORDER BY Value1
) foo
WHERE [Value1] / [Value1] > 3
0 голосов
/ 05 июня 2009

Кажется, вы ищете условное утверждение, IF.
http://msdn.microsoft.com/en-us/library/ms182717(SQL.90).aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...