SQL: левое соединение против подзапроса CASE - что более эффективно - PullRequest
0 голосов
/ 05 декабря 2018

Какой из них вы, ребята, считаете более эффективным (с меньшей нагрузкой)?

SELECT t1.a, 
(CASE
WHEN t1.p=1 THEN t2.g 
WHEN t1.p=2 THEN t3.g
END) as v

FROM t1
LEFT JOIN t2 ON t1.x=t2.x
LEFT JOIN t3 ON t1.y=t3.y

ИЛИ

SELECT 
t1.a, t2.v 

FROM t1    
outer apply (
SELECT v= CASE
WHEN t1.p=1 THEN (SELECT v FROM t2 WHERE t1.x=t2.x)
WHEN t1.p=2 THEN (SELECT v FROM t3 WHERE t1.y=t3.y)
END
) t2

Просто хочу выяснить, как работает sql engine ..

[Что я пытаюсь изучить в этом вопросе] В первом запросе таблицы всегда будут вызываться t2 и t3, но во втором запросе они будут вызываться только при совпадении регистра (и, следовательно, при меньшей загрузке = проверяются только 2 таблицы вместо 3 на строку)

Ответы [ 2 ]

0 голосов
/ 05 декабря 2018

Поместите дополнительный предикат t1.p= в каждое левое соединение, чтобы они стали взаимоисключающими по мере необходимости для результата.Это позволило бы использовать coalesce вместо выражения case (но с выражением case все в порядке, это просто опция).

Нет убедительной причины использовать оператор применения в вашем примере, и хотя они оптимизируют лучше, чем коррелированные подзапросы, помещенные в предложение select, они остаются коррелированными подзапросами.На мой взгляд, если нет веской причины для «более экзотического» варианта, не используйте его.Так что не используйте здесь оператор применения, перейдите к более стандартному левому соединению.

SELECT
    t1.a
  , COALESCE(t2.g,t3.g) AS v
FROM t1
LEFT JOIN t2 ON t1.x = t2.x AND t1.p = 1
LEFT JOIN t3 ON t1.y = t3.y AND t1.p = 2
;

Если, однако, у вас была функциональная потребность в одной (или предписанном количестве) строк из этих коррелированных подзапросов затем у вас будет веская причина использовать заявку, например

SELECT
    t1.a
  , t2.v
FROM t1
OUTER APPLY (
        SELECT
            CASE
                WHEN t1.p = 1 THEN (
                        SELECT TOP(1) t2.g FROM t2  -- top 
                        WHERE t1.x = t2.x
                        ORDER BY t2.z               -- order
                    )
                WHEN t1.p = 2 THEN (
                        SELECT TOP(1) t3.g FROM t3  -- top
                        WHERE t1.y = t3.y
                        ORDER BY t3.z               -- order
                    )
            END AS v
    ) t2

Независимо от мнения, использование планов выполнения - лучший способ для сравнения параметров запроса.

0 голосов
/ 05 декабря 2018

Я бы пошел с left join, но напишите это как:

SELECT t1.a, COALESCE(t2.g, t3.g) as v
FROM t1 LEFT JOIN
     t2
     ON t1.x = t2.x AND t1.p = 1 LEFT JOIN
     LEFT JOIN t3
     ON t1.y = t3.y AND t1.p = 2;

Эта логика не обязательно точно эквивалентна вашей логике, но я подозреваю, что этот запрос выполняет то, что вы намеревались.(Например, если t2.g когда-либо NULL и t1.p = 1, то результаты не совпадают.)

Что касается производительности, LEFT JOIN дает оптимизатору больше параметров для запроса, чемCASE выражение делает, так что, вероятно, будет быстрее.Однако при правильной индексации все три запроса, вероятно, имеют хорошую производительность.

...