Je veux trouver la quantité cumulative ou courante de champ et l'insérer de staging à table. Ma structure de mise en scène ressemble à ceci:
ea_month id amount ea_year circle_id
April 92570 1000 2014 1
April 92571 3000 2014 2
April 92572 2000 2014 3
March 92573 3000 2014 1
March 92574 2500 2014 2
March 92575 3750 2014 3
February 92576 2000 2014 1
February 92577 2500 2014 2
February 92578 1450 2014 3
Je veux que ma table cible ressemble à ceci:
ea_month id amount ea_year circle_id cum_amt
February 92576 1000 2014 1 1000
March 92573 3000 2014 1 4000
April 92570 2000 2014 1 6000
February 92577 3000 2014 2 3000
March 92574 2500 2014 2 5500
April 92571 3750 2014 2 9250
February 92578 2000 2014 3 2000
March 92575 2500 2014 3 4500
April 92572 1450 2014 3 5950
Je suis vraiment très confus quant à la manière d’atteindre ce résultat. Je veux atteindre ce résultat en utilisant PostgreSQL.
Quelqu'un peut-il suggérer comment s'y prendre pour atteindre cet ensemble de résultats?
En gros, vous avez besoin d'une fonction window ici. C'est une fonctionnalité standard de nos jours. En plus des fonctions de fenêtre authentiques, vous pouvez utiliser any la fonction d'agrégat comme fonction de fenêtre dans Postgres en ajoutant une clause OVER
.
La difficulté particulière ici est d'obtenir des partitions et un ordre de tri correct:
SELECT ea_month, id, amount, ea_year, circle_id
, sum(amount) OVER (PARTITION BY circle_id ORDER BY ea_year, ea_month) AS cum_amt
FROM tbl
ORDER BY circle_id, month;
Et nonGROUP BY
Ici.
La somme de chaque ligne est calculée à partir de la première ligne de la partition jusqu'à la ligne actuelle - ou entre guillemets le manuel pour être précis:
L'option de cadrage par défaut est
RANGE UNBOUNDED PRECEDING
, Identique àRANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
. AvecORDER BY
, Le cadre est défini comme suit . Toutes les lignes de la partition démarrent via le dernier pairORDER BY
De la ligne actuelle .
... qui est la somme cumulée ou courante que vous recherchez. Gras accent mien.
Les lignes avec le même (circle_id, ea_year, ea_month)
Sont "pairs" dans cette requête. Tous affichent la même somme en cours, tous les pairs ajoutés à la somme. Mais je suppose que votre table est UNIQUE
sur (circle_id, ea_year, ea_month)
, L'ordre de tri est alors déterministe et aucune ligne n'a de pairs.
Maintenant, ORDER BY ... ea_month
ne fonctionnera pas avec les chaînes pour les noms de mois. Postgres serait trié alphabétiquement en fonction des paramètres régionaux.
Si vous avez des valeurs réelles de date
stockées dans votre table, vous pouvez trier correctement. Sinon, je suggère de remplacer ea_year
Et ea_month
Par une seule colonne mon
de type date
dans votre table.
Transformez ce que vous avez avec to_date()
:
to_date(ea_year || ea_month , 'YYYYMonth') AS mon
Pour l'affichage, vous pouvez obtenir les chaînes d'origine avec to_char()
:
to_char(mon, 'Month') AS ea_month
to_char(mon, 'YYYY') AS ea_year
Bien que coincé avec la mise en page malheureuse, cela fonctionnera:
SELECT ea_month, id, amount, ea_year, circle_id
, sum(amount) OVER (PARTITION BY circle_id ORDER BY mon) AS cum_amt
FROM (SELECT *, to_date(ea_year || ea_month, 'YYYYMonth') AS mon FROM tbl)
ORDER BY circle_id, mon;