Соединение SQL выполняет только минимальное количество условий? - PullRequest
3 голосов
/ 28 февраля 2012

В C #, если я запускаю следующее.

if(obj.a() && obj.b()){
    // do something
}

Функция b будет выполняться, только если a вернет true.Происходит ли то же самое ниже?

select
    *
from
    tablea a
    inner join tableb b
        isnumeric(b.col1) = 1
        and cast(b.col1 as int) = a.id

Будет ли cast выполняться только тогда, когда b.col1 является числовым?

Ответы [ 3 ]

2 голосов
/ 28 февраля 2012

Вы можете симулировать оценку короткого замыкания, используя выражение CASE.

ON CASE WHEN ISNUMERIC(b.col1) = 1
       THEN CAST(b.col1 AS int)
       ELSE NULL
   END = a.id
2 голосов
/ 28 февраля 2012

Это глубоко охватывает оценку короткого замыкания в SQL-Server:

http://www.sqlservercentral.com/articles/T-SQL/71950/

Вкратце: порядок оценки зависит от оптимизатора запросов.

Редактировать : Как прокомментировал Мартин, это не гарантирует порядок, поскольку он также может быть оптимизирован. По ссылке выше (я должен был прочитать это полностью):

При запуске с SQL Server 2000 ошибка не выдается, но SQL Server 2005 и 2008 внедряют оптимизацию, чтобы выдвинуть non-SARGable предикаты в просмотр индекса из подзапроса, который вызывает заявление не выполнено.

Чтобы избежать этой проблемы, запрос может быть переписан с использованием CASE выражение, может быть, немного неясное, но гарантированно не потерпит неудачу.

Так что это должно гарантировать, что ISNUMERIC будет оцениваться первым:

SELECT aData.*,bData.*
FROM #TableA aData INNER JOIN  #TableB bData
ON aData.id = CASE ISNUMERIC(bData.col1) WHEN 1 THEN CAST(bData.col1 AS INT) END

Не обращайте внимания на мой первый подход (который может работать не каждый раз):

Вы должны изменить свое объединение, чтобы обеспечить его правильную оценку :

SELECT aData.*,bData.*
FROM #TableA aData INNER JOIN 
(
    SELECT col1
    FROM #TableB b
    WHERE ISNUMERIC(b.col1) = 1
 ) AS bData
 ON aData.id = CAST(bData.Col1 AS int)

Пример данных:

create table #TableA(id int)
create table #TableB(col1 varchar(10))

insert into #TableA values(1);
insert into #TableA values(2);
insert into #TableA values(3);
insert into #TableA values(4);

insert into #TableB values('1');
insert into #TableB values('2');
insert into #TableB values(null);
insert into #TableB values('4abc');

SELECT aData.*,bData.*
FROM #TableA aData INNER JOIN 
(
    SELECT col1
    FROM #TableB b
    WHERE ISNUMERIC(b.col1) = 1
 ) AS bData
 ON aData.id = CAST(bData.Col1 AS int)

drop table #TableA;
drop table #TableB;

Результат:

id  col1
1    1
2    2
1 голос
/ 28 февраля 2012

С ЗДЕСЬ :

Нет.Если приоритет не определяется форматами или круглыми скобками, эффективная оценка выражений обычно выполняется слева направо.Однако зависит от того, выполняются ли выражения на самом деле слева направо, особенно когда операнды или операторы могут вызывать условия, или если результаты выражений могут быть определены без полной оценки всех частей выражения.

...