Tableau d'agrégation PostgreSQL

95

Salut j'ai deux tables

Student
--------
Id  Name
1   John    
2   David
3   Will

Grade
---------
Student_id  Mark
1           A
2           B
2           B+
3           C
3           A

Est-il possible de faire une sélection native de Postgresql pour obtenir des résultats comme celui-ci:

Name    Array of marks
-----------------------
'John',     {'A'}
'David',    {'B','B+'}
'Will',     {'C','A'}

Mais pas comme ça

Name    Mark
----------------
'John',     'A'
'David',    'B'
'David',    'B+'
'Will',     'C'
'Will',     'A'
Eazy
la source

Réponses:

162

Utilisez array_agg: http://www.sqlfiddle.com/#!1/5099e/1

SELECT s.name,  array_agg(g.Mark) as marks        
FROM student s
LEFT JOIN Grade g ON g.Student_id = s.Id
GROUP BY s.Id

Au fait, si vous utilisez Postgres 9.1, vous n'avez pas besoin de répéter les colonnes de SELECT à GROUP BY, par exemple, vous n'avez pas besoin de répéter le nom de l'étudiant sur GROUP BY. Vous pouvez simplement GROUP BY sur la clé primaire. Si vous supprimez la clé primaire de l'étudiant, vous devez répéter le nom de l'étudiant sur GROUP BY.

CREATE TABLE grade
    (Student_id int, Mark varchar(2));

INSERT INTO grade
    (Student_id, Mark)
VALUES
    (1, 'A'),
    (2, 'B'),
    (2, 'B+'),
    (3, 'C'),
    (3, 'A');


CREATE TABLE student
    (Id int primary key, Name varchar(5));

INSERT INTO student
    (Id, Name)
VALUES
    (1, 'John'),
    (2, 'David'),
    (3, 'Will');
Michael Buen
la source
2
Oh mon dieu merci beaucoup pour votre remarque sur select / group, c'est tellement génial! C'était vraiment ennuyeux!
mrbrdo
8

Ce que je comprends, vous pouvez faire quelque chose comme ceci:

SELECT p.p_name, 
    STRING_AGG(Grade.Mark, ',' ORDER BY Grade.Mark) As marks
FROM Student
LEFT JOIN Grade ON Grade.Student_id = Student.Id
GROUP BY Student.Name;

ÉDITER

Je ne suis pas sûr. Mais peut-être quelque chose comme ça alors:

SELECT p.p_name, 
    array_to_string(ARRAY_AGG(Grade.Mark),';') As marks
FROM Student
LEFT JOIN Grade ON Grade.Student_id = Student.Id
GROUP BY Student.Name;

Référence ici

Arion
la source
Je pense qu'il veut un tableau pgsql, pas une chaîne séparée par des
virgules
0

@Michael Buen a bien compris. J'ai obtenu ce dont j'avais besoin en utilisant array_agg.

Voici juste un exemple de requête de base au cas où cela aiderait quelqu'un:

SELECT directory, ARRAY_AGG(file_name) FROM table WHERE type = 'ZIP' GROUP BY directory;

Et le résultat était quelque chose comme:

parent_directory | array_agg | ------------------------+----------------------------------------+ /home/postgresql/files | {zip_1.zip,zip_2.zip,zip_3.zip} | /home/postgresql/files2 | {file1.zip,file2.zip} |


Cet article m'a également beaucoup aidé: "Group By" en SQL et Python Pandas . Il dit essentiellement qu'il est plus pratique d'utiliser uniquement SQL lorsque cela est possible, mais que Python Pandas peut être utile pour obtenir des fonctionnalités supplémentaires dans le processus de filtrage.

J'espère que ça aide

Javi
la source