66 votes

Calculer un total cumulé dans MySQL

J'ai cette requête MySQL:

 SELECT DAYOFYEAR(`date`)  AS d, COUNT(*) 
FROM  `orders` 
WHERE  `hasPaid` > 0
GROUP  BY d
ORDER  BY d
 

Ce qui retourne quelque chose comme ceci:

 d  | COUNT(*) |
20 |  5       |
21 |  7       |
22 | 12       |
23 |  4       |
 

Ce que j'aimerais vraiment, c'est une autre colonne à la fin pour afficher le total cumulé:

 d  | COUNT(*) | ??? |
20 |  5       |   5 |
21 |  7       |  12 |
22 | 12       |  24 |
23 |  4       |  28 |
 

Est-ce possible?

124voto

Autosoft Points 476

Peut-être une solution plus simple pour vous et empêche la base de données d'avoir à faire une tonne de requêtes. Ceci n’exécute qu’une requête, puis effectue un petit calcul sur les résultats en un seul passage.

 SET @runtot:=0;
SELECT
   q1.d,
   q1.c,
   (@runtot := @runtot + q1.c) AS rt
FROM
   (SELECT
       DAYOFYEAR(`date`) AS d,
       COUNT(*) AS c
    FROM  `orders`
    WHERE  `hasPaid` > 0
    GROUP  BY d
    ORDER  BY d) AS q1
 

Cela vous donnera une colonne RT supplémentaire (total cumulé). Ne manquez pas l’instruction SET en haut pour initialiser la variable du total en cours d’exécution ou vous obtiendrez simplement une colonne de valeurs NULL.

11voto

cdonner Points 17403
SELECT 
   DAYOFYEAR(O.`date`)  AS d, 
   COUNT(*),
   (select count(*) from `orders` 
       where  DAYOFYEAR(`date`) <= d and   `hasPaid` > 0)
FROM  
  `orders` as O
WHERE  
  O.`hasPaid` > 0
GROUP  BY d
ORDER  BY d

Cela exigera des syntaxiques tuning (je n'ai pas de MySQL pour le tester), mais il vous montre l'idée. La sous-requête suffit de revenir en arrière et ajouter tout frais que vous avez déjà inclus dans la requête externe, et il doit le faire pour chaque ligne.

Jetez un oeil à cette question pour savoir comment utiliser les jointures pour accomplir la même.

Pour répondre aux préoccupations concernant la dégradation de la performance avec la croissance des données: Puisqu'il y a max. 366 jours pour une année, et je suppose que vous n'êtes pas l'exécution de cette requête à l'encontre de plusieurs années, la sous-requête est évalué jusqu'à 366 fois. Avec les bons indices sur la date et le hasPaid drapeau, vous serez ok.

0voto

Sergej Andrejev Points 4052

Je dirais que c'est impossible, chaque ligne résultante doit être indépendante. Utiliser un langage de programmation pour obtenir ces valeurs

0voto

Sam Points 1349

À moins que vous n'ayez d'autre choix que de le faire en SQL, je ferais la somme des résultats dans le langage de programmation qui effectue la requête. Un nid comme celui-ci deviendra très lent à mesure que la table s'agrandit.

0voto

TFD Points 10618

Vous pouvez pirater cela à l'aide de l'instruction Cross Join ou de quelques jointures slef, mais cela ralentira avec les grands ensembles de données. Il est donc probablement préférable de le faire dans un processeur post-requête; soit le curseur du code client

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X