Pregunta

Tengo una consulta SQL que une una tabla de precios a una tabla que contiene respuestas proporcionadas por el usuario. Mi consulta se utiliza para obtener el precio en función de la cantidad ingresada. A continuación se muestra mi declaración 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

El problema es que SQL Server ejecuta la cláusula where antes de JOIN y arroja el error:

  

La conversión falló al convertir el   valor varchar 'PRUEBA' para el tipo de datos int.

porque está haciendo las comparaciones mínimas y máximas antes de la unión ('PRUEBA' es un valor válido ingresado por el usuario en la tabla JobQuestion, pero no debe devolverse cuando JobQuestion se une a Price). Creo que SQL Server está eligiendo ejecutar WHERE porque, por alguna razón, el analizador cree que sería una consulta más eficiente. Si solo corro

SELECT JobQuestion.Value, Price.Min, Price.Max, Price.Amount FROM Price
    INNER JOIN JobQuestion 
        ON Price.QuestionFK=JobQuestion.QuestionFK
        AND JobQuestion.JobFK=1

Obtengo estos resultados:

500 1       500     272.00
500 501     1000    442.00
500 1001    2000    782.00

Entonces, agregar WHERE debería filtrar los dos últimos y simplemente devolver el primer registro. ¿Cómo fuerzo a SQL a ejecutar JOIN primero o utilizo otra técnica para filtrar solo los registros que necesito?

¿Fue útil?

Solución

Primero, este es un signo muy probable de diseño deficiente.
Si no puede cambiar el esquema, entonces tal vez podría forzar este comportamiento utilizando sugerencias . Cita:

  

Las sugerencias son opciones o estrategias especificadas para la aplicación por parte del procesador de consultas de SQL Server en las instrucciones SELECT, INSERT, UPDATE o DELETE. Las sugerencias anulan cualquier plan de ejecución que el optimizador de consultas pueda seleccionar para una consulta.

Y algo más:

  

Precaución:
  Debido a que el optimizador de consultas de SQL Server generalmente selecciona el mejor plan de ejecución para una consulta, recomendamos que & Lt; join_hint > ;, < query_hint > ;, y < table_hint > ser utilizado solo como último recurso por desarrolladores experimentados y administradores de bases de datos.

Otros consejos

Pruebe " reformulando " la consulta de la siguiente manera:

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

Según la respuesta de Christian Hayter, si tiene la opción, cambie el diseño de la tabla =)

No deberías comparar cadenas con ints. Si tiene alguna influencia sobre el diseño de su tabla, divida los dos usos diferentes de la columna JobQuestion.Value en dos columnas diferentes.

En caso de que no tenga influencia sobre el diseño de su tabla, ¿podría intentar filtrar esos registros con valores numéricos usando ISNUMERIC ()? Supongo que agregar esto a su cláusula where podría ayudar.

Es probable que pueda eliminar el where ... y simplemente agregarlos como predicados a su unión. Como es una unión interna, esto debería 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

Puede usar TRY_PARSE sobre esas columnas de cadenas para convertir a numérico, y si SQL no puede convertir, obtendrá NULL en lugar de mensaje de error.

P.S. Esto se introdujo por primera vez en SQL 2012, por lo que podría ser útil.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top