Eu tenho uma consulta assim:
SELECT ordIdent.Identifier, ord.OrderId
FROM OrderIdentifier ordIdent
JOIN [order] ord
ON ordIdent.OrderId = ord.OrderId
WHERE ordIdent.Identifier = '29584'
OR ord.ClientOrderId = '29584'
A ideia é que estamos pesquisando usando o valor '29584' e não sabemos realmente se é a ClientOrderId
ou an Identifier
, então queremos pesquisar ambos.
Isso dá um desempenho realmente muito ruim. Ele puxa milhões de linhas (125 mil de uma e 20 milhões da outra)
Mas esta consulta:
SELECT ordIdent.Identifier, ord.OrderId
FROM OrderIdentifier ordIdent
JOIN [order] ord
ON ordIdent.OrderId = ord.OrderId
WHERE ord.ClientOrderId = '01193504'
UNION
SELECT ordIdent.Identifier, ord.OrderId
FROM OrderIdentifier ordIdent
JOIN [order] ord
ON ordIdent.OrderId = ord.OrderId
WHERE ordIdent.Identifier = '01193504'
tem bom desempenho. Normalmente eu apenas faria isso e encerraria o dia.
Mas minha consulta real é muito grande e eu prefiro não chamá-la duas vezes (embora ainda seja melhor do que usar o "ou".) se eu tiver outras opções.
Parece que eu deveria fazer algum tipo de junção à esquerda para fazer isso funcionar. Mas eu não consigo envolver minha cabeça em torno disso.
Existe uma maneira de fazer isso em uma consulta que tenha uma junção à esquerda em vez de um "OR"? (Ou algum outro tipo de opção?)
ATUALIZAÇÃO:
OK, eu comecei a pensar sobre isso e percebi que poderia apenas fatorar o OR em um CTE que usa o union
e, em seguida, usar o CTE na consulta real.
Vou deixar isso em aberto caso haja uma maneira melhor de lidar com isso, mas um CTE corrige meu problema.
Eu acho que você pode reescrever essa consulta para usar um
FULL OUTER JOIN
:Mas por que você iria querer? Você acabará lendo todas as linhas de ambas as tabelas com essa sintaxe que causa o problema de desempenho que você está tentando evitar.
UNION
ouUNION ALL
é o caminho certo para ir aqui. Para filtros como você ainda pode usarUNION ALL
assim:Às vezes, há um pequeno benefício de desempenho ao fazer isso. Depende dos seus dados.