Matriz de agregação Postgresql


94

Oi eu tenho duas mesas

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

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

É possível fazer com que o Postgresql nativo selecione para obter resultados como este:

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

Mas não assim

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

Respostas:


161

Use 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

A propósito, se você estiver usando Postgres 9.1, você não precisa repetir as colunas em SELECT para GROUP BY, por exemplo, você não precisa repetir o nome do aluno em GROUP BY. Você pode simplesmente GROUP BY na chave primária. Se você remover a chave primária do aluno, precisará repetir o nome do aluno em 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
Oh meu Deus, muito obrigado sobre sua observação sobre select / group, isso é tão incrível! Isso foi realmente irritante!
mrbrdo

8

Pelo que entendi, você pode fazer algo assim:

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;

EDITAR

Não tenho certeza. Mas talvez algo assim então:

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;

Referência aqui


Acho que ele quer uma matriz pgsql, não uma string separada por vírgulas
ThiefMaster


0

@Michael Buen acertou. Consegui o que precisava usando array_agg.

Aqui está apenas um exemplo de consulta básica, caso ajude alguém:

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

E o resultado foi algo como:

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


Esse post também me ajudou muito: "Agrupar por" em SQL e Python Pandas . Basicamente, ele diz que é mais conveniente usar apenas SQL quando possível, mas que Python Pandas pode ser útil para obter funcionalidades extras no processo de filtragem.

Espero que ajude

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.