Tablica zagregowana Postgresql

96

Witam mam dwa stoliki

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

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

Czy możliwe jest wybranie natywnego Postgresql, aby uzyskać takie wyniki:

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

Ale nie tak

Name    Mark
----------------
'John',     'A'
'David',    'B'
'David',    'B+'
'Will',     'C'
'Will',     'A'
łatwy
źródło

Odpowiedzi:

166

Użyj 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

Nawiasem mówiąc, jeśli używasz Postgres 9.1, nie musisz powtarzać kolumn od SELECT do GROUP BY, np. Nie musisz powtarzać nazwiska ucznia w GROUP BY. Możesz po prostu GROUP BY na kluczu podstawowym. Jeśli usuniesz klucz podstawowy ucznia, musisz powtórzyć nazwisko ucznia w 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
źródło
2
O mój Boże, dziękuję bardzo za twoją uwagę na temat wyboru / grupy, to niesamowite! To było naprawdę irytujące!
mrbrdo
8

Rozumiem, że możesz zrobić coś takiego:

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;

EDYTOWAĆ

Nie jestem pewien. Ale może wtedy coś takiego:

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;

Odniesienie tutaj

Arion
źródło
Myślę, że chce tablicy pgsql, a nie ciągu oddzielonego przecinkami
ThiefMaster
0

@Michael Buen ma rację. Mam to, czego potrzebowałem, używając array_agg.

Oto przykład podstawowego zapytania na wypadek, gdyby komuś pomogło:

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

Wynik był taki:

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


Ten post również bardzo mi pomógł: „Grupuj według” w SQL i Python Pandas . Zasadniczo mówi się, że wygodniej jest używać tylko języka SQL, jeśli to możliwe, ale że Python Pandy mogą być przydatne do uzyskania dodatkowych funkcji w procesie filtrowania.

Mam nadzieję, że to pomoże

Javi
źródło