Как я могу оптимизировать этот запрос (ИЛИ внутри И проверки)? - PullRequest
2 голосов
/ 29 ноября 2011

У меня проблемы с этим запросом:

SELECT col1, col2,col3,...,coln FROM MyTable
WHERE col1 = @value1
AND
(
ISNULL(col2,'c') = ISNULL(@value2,ISNULL(col2,'c'))
OR
ISNULL(col3,'c') = ISNULL(@value2,ISNULL(col3,'c'))
)
 AND coln = 'valueN'

Я должен остановить казнь, это так медленно. Но редактирование:

SELECT col1, col2,col3,...,coln FROM MyTable
WHERE col1 = @value1
AND
(
ISNULL(col2,'c') = ISNULL(@value2,ISNULL(col2,'c'))
)
AND coln = 'valueN'

Этот запрос быстрее. Кто-нибудь может мне помочь? Как я могу заменить оператор или или заменить запрос, кроме проверки col1 и col2 ?. Спасибо.

UPDATE:

Большое спасибо, ребята. На самом деле мой запрос не использует '=', но использует 'Like', извините за это . Однако я использую ваши предложения, чтобы построить свой запрос, и он отлично работает:

SELECT col1, col2,col3,...,coln FROM MyTable
WHERE col1 like '%' + @value1 + '%'
AND
(
 (@value2 IS NULL)
 OR
  (col2 IS NOT NULL AND col2 LIKE '%' + @value2 + '%')
 OR
 (col3 IS NOT NULL AND col3 LIKE '%' + @value2 + '%')
)
 AND coln = 'valueN'

Я использую этот запрос со страницей, где у меня много полей для фильтрации поиска, и мне нужно, чтобы текстовое поле col2 применялось и к col3 в базе данных, я хочу сказать, только одно текстовое поле для name1 и name2 в базе данных.

Извините за мой неправильный вопрос и спасибо за ваши предложения.

Ответы [ 2 ]

3 голосов
/ 29 ноября 2011
ISNULL(col2,'c') = ISNULL('value2',ISNULL(col2,'c'))

совпадает с

col2 = 'value2' or (col2 is null and 'value2' is null)

Замените вхождения, и у вас, скорее всего, будет лучшая производительность.

Обновление

Существует одно принципиальное различие между этим решением и предложенным @onedaywhen: когда значение, указанное в 'value2' (я полагаю, является просто параметром, собранным в строку SQL), равно NULL, OP хочет только назад только записи, где col2 NULL. Присмотритесь к логике ОП, вы увидите это там. Логика OP всегда фильтрует: когда параметр равен NULL, OP хочет записи, где col2 is NULL.

@ onedaywhen решение приносит каждую запись, когда параметр NULL. Хотя это очень распространенный запрос, это не то, что ищет OP .

1 голос
/ 30 ноября 2011
ISNULL(col2,'c') = ISNULL(@value2,ISNULL(col2,'c'))

- это то же самое, что и

( ( col2 = @value2 ) OR ( @value2 IS NULL ) ) 

Я не уверен, что это улучшит производительность, хотя: я читал это, по крайней мере для SQL Server 2005 и более ранних версий, чтобы получить эффективное, масштабируемое и производительное решение, либо используйте IF ELSE управление блоками потока (по одному на комбинацию параметров), либо используйте динамический SQL .


UPDATE: ... и вот доказательство:


Запрос 1: когда параметр является значением, отличным от нуля:

DECLARE @value2 VARCHAR(10);
SET @value2 = 'Apples';
WITH T 
     AS 
     (
      SELECT * 
        FROM (
              VALUES (1, 'When col2 is null', NULL), 
                     (2, 'When col2 is the same value as @value2', 'Apples'), 
                     (3, 'When col2 is not the same value as @value2', 'Oranges')
             ) AS T (ID, narrative, col2)
     )
SELECT *, 
       CASE WHEN ISNULL(col2,'c') = ISNULL(@value2,ISNULL(col2,'c')) THEN 'T' END AS OP, 
       CASE WHEN ( ( col2 = @value2 ) OR ( @value2 IS NULL ) ) THEN 'T' END AS OneDayWhen, 
       CASE WHEN col2 = @value2 or (col2 is null and @value2 is null) THEN 'T' END AS Adrian
  FROM T;

Выход 1:

ID          narrative                                  col2    OP   OneDayWhen Adrian
----------- ------------------------------------------ ------- ---- ---------- ------
1           When col2 is null                          NULL    NULL NULL       NULL
2           When col2 is the same value as @value2     Apples  T    T          T
3           When col2 is not the same value as @value2 Oranges NULL NULL       NULL

Обратите внимание, что все согласны для всехlines:)


Запрос 2: Если параметр имеет значение NULL:

DECLARE @value2 VARCHAR(10);
SET @value2 = NULL;
WITH T 
     AS 
     (
      SELECT * 
        FROM (
              VALUES (1, 'When col2 is null', NULL), 
                     (2, 'When col2 is the same value as @value2', 'Apples'), 
                     (3, 'When col2 is not the same value as @value2', 'Oranges')
             ) AS T (ID, narrative, col2)
     )
SELECT *, 
       CASE WHEN ISNULL(col2,'c') = ISNULL(@value2,ISNULL(col2,'c')) THEN 'T' END AS OP, 
       CASE WHEN ( ( col2 = @value2 ) OR ( @value2 IS NULL ) ) THEN 'T' END AS OneDayWhen, 
       CASE WHEN col2 = @value2 or (col2 is null and @value2 is null) THEN 'T' END AS Adrian
  FROM T;

Выход 2:

ID          narrative                                  col2    OP   OneDayWhen Adrian
----------- ------------------------------------------ ------- ---- ---------- ------
1           When col2 is null                          NULL    T    T          T
2           When col2 is the same value as @value2     Apples  T    T          NULL
3           When col2 is not the same value as @value2 Oranges T    T          NULL

Примечание OP и OneDayWhen совпадают для всехстрок, Адриан соответствует только идентификатору строки = 1.

...