SQL: левое соединение против подзапроса CASE - что более эффективно
Какой из них вы, ребята, считаете более эффективным (с меньшей нагрузкой)?
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-м запросе они будут вызываться только в том случае, если регистр совпадает (и, следовательно, будет меньше load = проверено только 2 таблицы вместо 3 в строке)?
2 ответа
Поместите дополнительный предикат t1.p=
в каждом левом соединении, чтобы они стали взаимоисключающими по мере необходимости для результата. Это позволило бы использовать coalesce
вместо выражения case (но с выражением case все в порядке, это просто опция).
В вашем примере нет веской причины использовать оператор apply, и хотя они оптимизируют лучше, чем коррелированные подзапросы, помещенные в предложение select, они остаются коррелированными подзапросами. На мой взгляд, если нет веской причины для "более экзотического" варианта, не используйте его. Так что, не используйте здесь оператор apply, используйте более стандартное левое соединение.
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
Независимо от мнения, использование планов выполнения - лучший способ сравнить параметры запроса.
Я бы пошел с 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
выражение делает, так что, скорее всего, будет быстрее. Однако при правильной индексации все три запроса, вероятно, имеют хорошую производительность.