Mysql
 sql >> Base de données >  >> RDS >> Mysql

MySQL SUM() donnant un total incorrect

Vous rencontrez un aggregate fanout issue . Cela se produit chaque fois que la table primaire d'une requête de sélection comporte moins de lignes qu'une table secondaire à laquelle elle est jointe. La jointure produit des lignes en double. Ainsi, lorsque des fonctions d'agrégation sont appliquées, elles agissent sur des lignes supplémentaires.

Ici, la table primaire fait référence à celle où les fonctions d'agrégation sont appliquées. Dans votre exemple,
* SUM(matters.fee)>> agrégation sur table matters .
* SUM(advicetime*advicefee)>> agrégation sur table actions
fixedfee='Y'>> où la condition sur la table matters

Pour éviter le problème de sortance :
* Appliquez toujours les agrégats à la table la plus granulaire dans une jointure.
* À moins que deux tables n'aient une relation un-à-un, n'appliquez pas de fonctions d'agrégat sur les champs de les deux tables.
* Obtenez vos agrégats séparément via différentes sous-requêtes, puis combinez le résultat. Cela peut être fait dans une instruction SQL, ou vous pouvez exporter les données et ensuite le faire.

Requête 1 :

SELECT SUM(fee) AS totfixed 
FROM matters 
WHERE fixedfee='Y'

Requête 2 :

SELECT SUM(actions.advicetime*actions.advicefee) AS totbills 
FROM matters  
JOIN actions ON matters.matterid = actions.matterid 
WHERE matters.fixedfee = 'Y'

Query 1 &Query 2 ne souffrez pas de fanout. À ce stade, vous pouvez les exporter tous les deux et traiter le résultat en php. Ou vous pouvez les combiner en SQL :

SELECT query_2.totbills, query_1.totfixed
FROM (SELECT SUM(fee) AS totfixed 
    FROM matters 
    WHERE fixedfee='Y') query_1,

    (SELECT SUM(actions.advicetime*actions.advicefee) AS totbills 
    FROM matters  
    JOIN actions ON matters.matterid = actions.matterid 
    WHERE matters.fixedfee = 'Y') query_2

Enfin, SUM ne prend pas de mot clé DISTINCT . DISTINCT n'est disponible que pour COUNT et GROUP_CONCAT fonctions d'agrégation. Ce qui suit est un morceau de SQL invalide

SUM(DISTINCT matters.fee) AS totfixed