2010-07-26 5 views
2

J'ai 2 requêtes qui affichent 2 valeurs différentes mais les résultats d'une requête sont inattendus.MySQL se joint à la clause WHERE

Query1:

SELECT SUM(T.amount_reward_user) AS total_grouping 
    FROM fem_user_cards UC 
     LEFT JOIN fem_transactions T USING(card_number) 
     LEFT JOIN fem_company_login FCL 
         ON T.fem_company_login_id=FCL.fem_company_login_id 
    WHERE UC.fem_user_login_id=193 
         AND FCL.grouping<>0 AND T.from_group=1 AND T.authorised=1 
    GROUP BY UC.fem_user_login_id 

La requête ci-dessus me donne le montant total de récompense pour l'utilisateur 193. Ici la condition est le montant de la récompense que je reçois de cette requête doit être dans le groupe qui est évident à partir de T.from_group = 1. Donc, cela semble fonctionner correctement.

Query2:

SELECT SUM(T.amount_reward_user) AS total_grouping 
    FROM fem_transactions T 
LEFT JOIN fem_company_login FCL 
ON T.fem_company_login_id=FCL.fem_company_login_id 
    WHERE T.fem_user_login_id=193 
     AND FCL.grouping<>0 AND T.from_group=1 AND T.authorised=1 

Dans cette requête, même si T.from_group = 1, il ajoute le montant de la récompense de T.from_group = 0 aussi bien. Quelqu'un sait-il quel est le problème?

Par exemple:

L'utilisateur 193 acheté quelque chose dans une société A (dans le groupe si T.from_group = 1) pour 5 $ et a obtenu la récompense de 1 $ et achète un autre produit pour 5 $ de la société B (sur de groupe donc T.from_group = 0) et recevez à nouveau une récompense de 1 $.

Ma sortie attendue est: 1

Je reçois:

Query1: 1

Query2: 2

Je pourrais simplement utiliser la requête 1 mais j'ai des problèmes avec d'autres choses quand je l'utilise, donc j'ai besoin de comprendre ce qui se passe vraiment !!


Mon but est d'obtenir la somme des montants de récompense de la base de données. La somme devrait être de différentes sociétés groupées. C'est-à-dire si nous avons 5 sociétés groupées différentes et que l'utilisateur utilise sa carte de paiement dans ces 5 sociétés, je devrais obtenir 5 totaux différents. S'il a utilisé sa carte dans une société qui n'est pas dans le groupe, le total ne doit pas inclure la transaction de cette société non groupée. J'ai le code C++ pour alimenter la base de données au fur et à mesure des transactions. Ma table fem_transactions a company_id, amount_reward_user, fem_user_login_id, from_group (cela décide si l'utilisateur a transité hors du groupe ou du groupe), autorisé etc.

Je veux filtrer le montant dépensé par l'utilisateur 193 dans chaque groupe séparément.

J'ai compris les concepts JOINTS maintenant mais j'ai besoin de savoir pourquoi t.from_group sur la deuxième requête est ignoré?

+1

Vous devez poster quelques exemples de données et de la production qui démontrent le problème, ainsi que ce que vous attendez de la sortie. S'il vous plaît modifier votre question et ajouter cette information. –

+0

Je ne sais pas si cela va résoudre votre problème, mais vous avez besoin d'une meilleure compréhension des jointures à gauche et des clauses where. celui-ci est spécifique à SQL Server, mais le principe de base devrait être applicable à toutes les bases de données: http://wiki.lessthandot.com/index.php/WHERE_conditions_on_a_LEFT_JOIN – HLGEM

+0

Vous devriez éditer votre article original plutôt que de poster une réponse. En outre, nous devons voir un schéma de table. Je ne suis pas sûr de la façon dont le regroupement s'intègre dans le groupe par l'entreprise. – Thomas

Répondre

2

Le problème est que vous avez des critères dans la clause Where par rapport aux colonnes sur le côté droit de la jointure à gauche. Dans les deux requêtes, il s'agit de And FCL.grouping <> 0. Cela modifie effectivement la jointure gauche à une jointure interne puisque vous êtes dans exiger qu'une valeur FCL.grouping existe et ne pas être zéro (ou null). Ce que vous voulez, je pense, est de passer que les critères dans la clause sur:

première requête:

Select Sum(T.amount_reward_user) AS total_grouping 
From fem_user_cards UC 
    Left Join fem_transactions T Using(card_number) 
    Left Join fem_company_login FCL 
     On FCL.fem_company_login_id = T.fem_company_login_id 
      And FCL.grouping<>0 
Where UC.fem_user_login_id=193 
    And T.from_group=1 
    And T.authorised=1 
Group By UC.fem_user_login_id 

Deuxième requête

Select Sum(T.amount_reward_user) AS total_grouping 
From fem_transactions T 
    Left Join fem_company_login FCL 
     On FCL.fem_company_login_id = T.fem_company_login_id 
      And FCL.grouping<>0 
Where UC.fem_user_login_id=193 
    And T.from_group=1 
    And T.authorised=1 

Ce qui est moins clair dans tout cela est que vous essayez d'atteindre. C'est à dire., pourquoi même avoir les jointures à gauche dans l'une ou l'autre question si vous ne filtrez pas dessus. Si vous souhaitez spécifiquement filtrer les lignes où il existe une valeur fem_company_login avec une valeur de groupe <> 0, utilisez votre requête d'origine et modifiez la jointure gauche vers une jointure interne. Si vous souhaitez filtrer pour les personnes qui ont soit une valeur de regroupement <> 0 ou aucune valeur faire quelque chose comme:

Select Sum(T.amount_reward_user) AS total_grouping 
From fem_transactions T 
    Left Join fem_company_login FCL 
     On FCL.fem_company_login_id = T.fem_company_login_id 
Where UC.fem_user_login_id=193 
    And T.from_group=1 
    And T.authorised=1 
    And (FCL.PrimaryKeyColumn Is Null Or FCL.grouping <> 0) 
+0

Je n'étais pas au courant qu'une clause 'where' pouvait changer la signification d'une jointure. Je pensais que la sémantique était que la jointure se comportait comme si une table virtuelle était créée, en utilisant les critères de jointure, et que la clause 'where' était appliquée à cette table virtuelle. Pouvez-vous citer une référence pour votre description du comportement? –

+0

@Jim Garrison - C'est dans la nature de la jointure que cela fonctionne de cette façon. Lorsque vous utilisez une jointure à gauche, vous demandez tous les éléments sur la gauche et tous les éléments correspondants sur la droite. Si vous appliquez ensuite un filtre dans la clause Where sur une colonne d'une table à droite, et ne tenez pas compte de Null, vous demandez que la valeur A. Existe, B. ne soit pas nulle et C. correspond aux critères (c.-à-d. égal, non égal, supérieur à etc. selon l'opérateur). Ainsi, le critère 'FCL.grouping <> 0' indique qu'une ligne de FCL doit exister, elle doit avoir une valeur de regroupement non nulle et cette valeur ne doit pas être égale à 0. – Thomas

+0

@Jim Garrison - Poursuite, si vous appliquez un filtre ce qui nécessite l'existence d'une ligne sur le côté droit d'une jointure à gauche, vous effectuez ainsi une jointure interne. – Thomas