web-dev-qa-db-fra.com

La jointure externe gauche ne fonctionne pas?

J'ai une requête qui extrait des données de trois tables en utilisant LEFT OUTER JOIN pour les deux jointures. J'ai besoin de la requête pour renvoyer les informations les plus à gauche (table Salesrep) même s'il n'y a pas de données correspondantes dans les deux tables de droite (prescripteur et prescriptions, respectivement). Lorsque j'exécute cette requête sans les paramètres de date dans la clause WHERE, j'obtiens le retour attendu, mais dès que j'inclus les paramètres de date, je ne reçois rien de retourné là où il n'y a pas de données correspondantes pour un représentant de vente. Je dois au moins voir les colonnes de la table salesrep demandées dans la requête.

Voici la requête ... toute aide est TRÈS appréciée.

SELECT  salesrep.salesrepid as SalesRepID,
        salesrep.fname as SalesrepFName,
        salesrep.lname as SalesRepLName,
        salesrep.fname+' '+salesrep.lname as SalesRepFullName,
        prescriber.dea_no as PDeaNo,
        prescriber.lname+', '+prescriber.fname as DocName,
        CONVERT(VARCHAR(8), prescriptions.filldate, 1) as FillDate,
        prescriptions.drugname as DrugName,
        prescriptions.daysupply as Supply,
        prescriptions.qtydisp as QtyDisp,
        prescriptions.rx_no as Refill,
        prescriptions.copay as Sample,
        ROUND(prescriptions.AgreedToPay-(prescriptions.AgreedToPay*.07),2) as AgreedToPay,
        prescriptions.carrierid as CarrierID
FROM    salesrep
  LEFT OUTER JOIN prescriber on salesrep.salesrepid = prescriber.salesrepid
  LEFT OUTER JOIN prescriptions on prescriber.dea_no = prescriptions.dea_no
  WHERE salesrep.salesrepid = 143 AND
        prescriptions.filldate >= '09-01-12' AND
        prescriptions.filldate <= '09-17-12'
ORDER BY prescriptions.filldate
32
jgiven

Vous devez déplacer les contraintes sur prescriptions.filldate dans la condition ON de la jointure, et supprimez-la de la clause where:

LEFT OUTER JOIN prescriptions ON prescriber.dea_no = prescriptions.dea_no
                             AND prescriptions.filldate >= '09-01-12'
                             AND prescriptions.filldate <= '09-17-12'

Sinon, les entrées pour lesquelles il n'y a pas de prescriptions se terminent par nulls dans prescriptions.filldate, et la clause WHERE les jette.

67
dasblinkenlight

Ici vous pouvez trouver une brève description des phases de traitement des requêtes (c'est commun pour la plupart des SGBD). Vous découvrirez là, que pour OUTER JOIN:

  1. la première CARTESIAN JOIN est produite,
  2. que la condition ON est effectuée sur l'ensemble de résultats produisant un sous-ensemble de lignes,
  3. après que les lignes externes sont ajoutées avec des valeurs NULL sur les colonnes jointes de la table interne,
  4. sur ce résultat, la clause WHERE est appliquée en effectuant un filtrage.

Lorsque vous placez la condition dans la clause WHERE qui touche les lignes des tables externes, elles sont toutes supprimées. Vous devez simplement placer cette condition dans la clause ON, car celle-ci est évaluée avant que les lignes externes ne soient ajoutées.

Donc, ces conditions:

prescriptions.filldate >= '09-01-12' AND
prescriptions.filldate <= '09-17-12'

doit être déplacé dans la clause ON.

14
WojtusJ

C'est parce que votre prescriptions.filldate les inégalités filtrent vos salesrep lignes qui n'ont pas de valeur dans le prescriptions.filldate colonne.

Donc, s'il y a des valeurs nulles (pas de données correspondantes dans les bonnes tables), alors la ligne entière, y compris les données salesrep, est filtrée par les filtres de date - car le null ne se situe pas entre les deux dates.

0
xelco52