Question

J'ai une requête SQL qui joint une table de tarification à une table contenant des réponses fournies par l'utilisateur. Ma requête est utilisée pour obtenir le prix en fonction de la quantité entrée. Ci-dessous ma déclaration 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

Le problème est que SQL Server exécute la clause where avant le JOIN et renvoie l'erreur:

  

La conversion a échoué lors de la conversion du   Valeur varchar 'TEST' pour le type de données int.

car il fait les comparaisons min et max avant la jointure ('TEST' est une valeur entrée par l'utilisateur valide dans la table JobQuestion, mais ne doit pas être renvoyée lorsque JobQuestion est joint à Price). Je pense que SQL Server choisit d’exécuter le WHERE car, pour une raison quelconque, l’analyseur pense que ce serait une requête plus efficace. Si je viens de courir

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

Je récupère ces résultats:

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

Ainsi, l'ajout du WHERE devrait filtrer les deux derniers et simplement renvoyer le premier enregistrement. Comment forcer SQL à exécuter en premier le JOIN ou à utiliser une autre technique pour filtrer uniquement les enregistrements dont j'ai besoin?

Était-ce utile?

La solution

Tout d’abord, c’est très probablement un signe de mauvaise conception.
Si vous ne pouvez pas modifier le schéma, vous pourriez peut-être forcer ce comportement à l'aide des astuces Citation:

  

Les astuces sont des options ou des stratégies spécifiées pour être appliquées par le processeur de requêtes SQL Server sur les instructions SELECT, INSERT, UPDATE ou DELETE. Les astuces remplacent tout plan d'exécution que l'optimiseur de requête peut sélectionner pour une requête.

Et d'autres encore:

  

Attention:
  Étant donné que l'optimiseur de requêtes SQL Server sélectionne généralement le meilleur plan d'exécution pour une requête, nous vous recommandons d'utiliser & Lt; join_hint > ;, < query_hint > ;, et < table_hint > être utilisé qu'en dernier recours par des développeurs expérimentés et des administrateurs de bases de données.

Autres conseils

Essayez & "; reformulez &"; la requête comme suit:

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

Selon la réponse de Christian Hayter, si vous avez le choix, changez le format de la table =)

Vous ne devriez pas comparer les chaînes à ints. Si vous avez une quelconque influence sur la conception de votre table, divisez les deux utilisations différentes de la JobQuestion.Value colonne en deux colonnes différentes.

Au cas où vous n’auriez aucune influence sur la conception de votre table - Pourriez-vous essayer de filtrer ces enregistrements avec des valeurs numériques en utilisant ISNUMERIC ()? J'imagine que l'ajout de ceci à votre clause "où" pourrait vous aider.

Vous pouvez probablement supprimer les éléments where ... et simplement les ajouter en tant que prédicats à votre jointure. Comme il s’agit d’une jointure interne, cela devrait fonctionner

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

Vous pouvez utiliser TRY_PARSE sur les chaînes de chaînes à convertir en valeurs numériques. Si SQL ne peut pas être converti, vous obtiendrez NULL au lieu du message d'erreur.

P.S. Cette fonctionnalité est introduite pour la première fois dans SQL 2012, elle pourrait donc être utile.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top