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

combinaison du résultat de la requête mysql SUM () à l'aide d'une jointure interne

Construisez d'abord la somme, puis joignez-vous. Comme ceci :

SELECT i.uid
      ,i.date
      ,i.v_in
      ,COALESCE(o.v_out, 0) AS v_out
      ,(i.v_in - COALESCE(o.v_out, 0)) AS balance
FROM (
    SELECT date
          ,uid
          ,SUM(value_in) AS v_in
    FROM   table1
    GROUP  BY 1,2
    ) i
LEFT JOIN (
    SELECT date
          ,uid
          ,SUM(value_out) AS v_out
    FROM   table2
    GROUP  BY 1,2
    ) o USING (date, uid)

Comme vous l'aviez, chaque value_in serait combiné avec chaque value_out correspondant , multipliant ainsi les nombres. Vous devez d'abord agréger, puis rejoindre un en somme avec un out-sum et tout est groovy. Ou est-ce ?

Que se passe-t-il s'il n'y a pas de value_in ou value_out pour un (date, uid) donné ? Ou seulement value_in Ou juste value_out ? Votre requête échouera.

J'ai amélioré en utilisant un LEFT JOIN au lieu de [INNER] JOIN , mais ce que vous voulez vraiment, c'est un FULL OUTER JOIN - une des fonctionnalités manquantes dans MySQL.

Vous pouvez soit fournir une liste de jours dans un tableau séparé et LEFT JOIN les deux tables, ou vous pouvez contourner la fonctionnalité manquante avec deux fois LEFT JOIN et UNION . Voir ici pour un exemple .

Ou vous pouvez multiplier votre value_out par -1 UNION les deux tables ensemble et construisez une somme.

Mais vous toujours n'obtiendrait pas une ligne pendant une journée sans aucun value_in ou value_out , ce qui ne respecte pas votre description.

Donc, la seule solution propre est d'avoir une table avec tous les (date, uid) vous voulez dans le résultat et LEFT JOIN les sommes de table1 et table2 ou UNION ALL les trois (négatif table2 ) dans une sous-sélection puis résumer.