Сукупний масив Postgresql


95

Привіт у мене є дві таблиці

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

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

Чи можна зробити рідний Postgresql вибрати, щоб отримати такі результати:

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

Але не так

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

Відповіді:


163

Використовуйте 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

До речі, якщо ви використовуєте Postgres 9.1, вам не потрібно повторювати стовпці в SELECT to GROUP BY, наприклад, вам не потрібно повторювати ім'я студента в GROUP BY. Ви можете просто GROUP BY за первинним ключем. Якщо ви видалите первинний ключ на студента, вам потрібно повторити ім’я студента на 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');

2
Боже мій, дякую тобі дуже за твоє зауваження щодо відбору / групи, це надзвичайно! Це справді дратувало!
mrbrdo

8

Наскільки я розумію, ви можете зробити щось подібне:

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;

РЕДАГУВАТИ

Я не впевнений. Але, можливо, щось подібне тоді:

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;

Довідка тут


Я думаю, що він хоче масив pgsql, а не рядок, відокремлений комами
ThiefMaster


0

@Michael Buen все зрозумів. Я отримав те, що мені потрібно, використовуючи array_agg.

Ось лише базовий приклад запиту на випадок, якщо це комусь допоможе:

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

І результат був приблизно такий:

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


Ця публікація також мені дуже допомогла: "Групувати" у SQL та Python Pandas . В основному сказано, що зручніше використовувати лише SQL, коли це можливо, але що Python Pandas може бути корисним для досягнення додаткових функціональних можливостей у процесі фільтрації.

Сподіваюся, це допоможе

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.