Como faço para forçar o SQL Server 2005 para executar uma junção antes da onde?
-
10-07-2019 - |
Pergunta
Eu tenho uma consulta SQL que se junta a uma tabela de preços para uma tabela contendo as respostas fornecidas pelo usuário. Minha pergunta é usado para obter o preço baseado na quantidade inserida. Abaixo está a minha declaração SQL:
SELECT JobQuestion.Value, Price.Min, Price.Max, Price.Amount FROM Price
INNER JOIN JobQuestion
ON Price.QuestionFK=JobQuestion.QuestionFK
AND JobQuestion.JobFK=1
WHERE Price.Min <= JobQuestion.Value
AND Price.Max >= JobQuestion.Value
O problema é SQL Server está em execução a cláusula WHERE antes da JOIN e ele está jogando o erro:
A conversão falhou ao converter o valor varchar 'teste' para tipo de dados int.
porque ele está fazendo o min e comparações máximo antes da junção ( 'teste' é um usuário válido valor inserido na tabela de JobQuestion, mas não deve ser devolvido quando JobQuestion se une ao preço). Eu acredito que o SQL Server está escolhendo para executar o ONDE porque, por algum motivo, o analisador pensa que seria uma consulta mais eficiente. Se eu executar
SELECT JobQuestion.Value, Price.Min, Price.Max, Price.Amount FROM Price
INNER JOIN JobQuestion
ON Price.QuestionFK=JobQuestion.QuestionFK
AND JobQuestion.JobFK=1
Eu recebo estes resultados de volta:
500 1 500 272.00
500 501 1000 442.00
500 1001 2000 782.00
Assim, adicionando o ONDE deve filtrar os dois últimos e apenas retornar o primeiro registro. Como faço para forçar o SQL para executar o JOIN primeiro ou usar outra técnica para filtrar apenas os registros que eu preciso?
Solução
Em primeiro lugar, este é muito provável sinal de má concepção.
Se você não pode mudar o esquema, então talvez você poderia forçar este comportamento usando dicas . Citação:
Sugestões são opções ou estratégias específicas para a aplicação pelo processador de consulta SQL Server em SELECT, INSERT, UPDATE, ou instruções DELETE. As sugestões substituir qualquer plano de execução do otimizador de consulta pode seleccionar para uma consulta.
E um pouco mais:
Atenção:
Porque o otimizador de consulta SQL Server normalmente seleciona o melhor plano de execução para uma consulta, recomendamos que, e ser usado apenas como um último recurso por desenvolvedores experientes e administradores de banco de dados.
Outras dicas
Tente "re-fraseado" a consulta da seguinte maneira:
SELECT *
FROM (
SELECT JobQuestion.Value,
Price.Min,
Price.Max,
Price.Amount
FROM Price
INNER
JOIN JobQuestion
ON Price.QuestionFK = JobQuestion.QuestionFK
AND JobQuestion.JobFK = 1
) SQ
WHERE SQ.Min <= SQ.Value
AND SQ.Max >= SQ.Value
De acordo com a resposta de Christian Hayter, se você tem a opção, mudar o design da tabela =)
Você não deve estar comparando cordas para ints. Se você tem alguma influência em todo o design da tabela, em seguida, dividir os dois usos diferentes da coluna JobQuestion.Value
em duas colunas diferentes.
No caso de você não tem nenhuma influência sobre o design da tabela - Você poderia tentar para filtrar os registros com valores numéricos usando IsNumeric ()? Eu acho adicionando isso ao seu onde cláusula poderia ajudar.
Você pode provavelmente remover o onde ... e apenas adicionar aqueles como predicados a sua juntar-se. Desde que é participar de um interior isso deve funcionar
SELECT JobQuestion.Value, Price.Min, Price.Max, Price.Amount
FROM Price
INNER JOIN JobQuestion
ON Price.QuestionFK=JobQuestion.QuestionFK
AND JobQuestion.JobFK=1
AND Price.Min <= JobQuestion.Value
AND Price.Max >= JobQuestion.Value
Você pode usar TRY_PARSE mais que as cordas colunas para converter para numérico, e se SQL não pode converter, ele vai te nulo em vez de mensagem de erro.
P.S. Esta coisa é primeira vez introduzido no SQL 2012, por isso pode ser útil.