217 votes

Regrouper les résultats d'une requête par mois et par année dans postgresql

J'ai la table de base de données suivante sur un serveur Postgres :

id      date          Product Sales
1245    01/04/2013    Toys    1000     
1245    01/04/2013    Toys    2000
1231    01/02/2013    Bicycle 50000
456461  01/01/2014    Bananas 4546

J'aimerais créer une requête qui donne les résultats suivants SUM de la Sales et regroupe les résultats par mois et par année comme suit :

Apr    2013    3000     Toys
Feb    2013    50000    Bicycle
Jan    2014    4546     Bananas

Y a-t-il un moyen simple de le faire ?

404voto

Burak Arslan Points 4065

Je ne peux pas croire que la réponse acceptée ait autant de votes positifs - c'est une méthode horrible.

Voici la manière correcte de le faire, avec date_tronc :

   SELECT date_trunc('month', txn_date) AS txn_month, sum(amount) as monthly_sum
     FROM yourtable
 GROUP BY txn_month

C'est une mauvaise pratique mais vous pouvez être pardonné si vous utilisez

 GROUP BY 1

dans une requête très simple.

Vous pouvez également utiliser

 GROUP BY date_trunc('month', txn_date)

si vous ne voulez pas sélectionner la date.

251voto

bma Points 2807
select to_char(date,'Mon') as mon,
       extract(year from date) as yyyy,
       sum("Sales") as "Sales"
from yourtable
group by 1,2

À la demande de Radu, je vais expliquer cette requête :

to_char(date,'Mon') as mon, La fonction "date" : convertit l'attribut "date" dans le format défini de la forme courte du mois.

extract(year from date) as yyyy : La fonction "extract" de Postgresql est utilisée pour extraire l'année YYYY de l'attribut "date".

sum("Sales") as "Sales" : La fonction SUM() additionne toutes les valeurs "Sales", et fournit un alias sensible à la casse, la sensibilité à la casse étant maintenue par l'utilisation de guillemets doubles.

group by 1,2 : La fonction GROUP BY doit contenir toutes les colonnes de la liste SELECT qui ne font pas partie de l'agrégat (aka, toutes les colonnes qui ne sont pas à l'intérieur des fonctions SUM/AVG/MIN/MAX etc). Cela indique à la requête que la fonction SUM() doit être appliquée pour chaque combinaison unique de colonnes, qui dans ce cas sont les colonnes mois et année. La partie "1,2" est un raccourci au lieu d'utiliser les alias de colonnes, bien qu'il soit probablement préférable d'utiliser les expressions complètes "to_char(...)" et "extract(...)" pour plus de lisibilité.

49voto

mgoldwasser Points 377

to_char vous permet en fait de sortir l'année et le mois d'un seul coup !

select to_char(date('2014-05-10'),'Mon-YY') as year_month; --'May-14'
select to_char(date('2014-05-10'),'YYYY-MM') as year_month; --'2014-05'

ou dans le cas de l'exemple de l'utilisateur ci-dessus :

select to_char(date,'YY-Mon') as year_month
       sum("Sales") as "Sales"
from some_table
group by 1;

7voto

Nayan Points 36

Il existe un autre moyen d'obtenir ce résultat en utilisant la fonction date_part() de postgres.

 SELECT date_part('month', txn_date) AS txn_month, date_part('year', txn_date) AS txn_year, sum(amount) as monthly_sum
     FROM yourtable
 GROUP BY date_part('month', txn_date)

Merci

5voto

Lucas Kuhn Points 121

Jetez un coup d'œil à l'exemple 6) de ce tutoriel -> https://www.postgresqltutorial.com/postgresql-group-by/

Vous devez appeler la fonction sur votre GROUP BY au lieu d'appeler le nom de l'attribut virtuel que vous avez créé sur select. Je faisais ce que toutes les réponses ci-dessus recommandaient et j'obtenais un message d'erreur column 'year_month' does not exist erreur.

Ce qui a marché pour moi, c'est :

SELECT 
    date_trunc('month', created_at), 'MM/YYYY' AS month
FROM 
    "orders"  
GROUP BY 
    date_trunc('month', created_at)

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