Matriz agregada de Postgresql

95

Hola tengo dos mesas

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

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

¿Es posible hacer que Postgresql nativo seleccione para obtener resultados como este:

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

Pero no asi

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

Respuestas:

163

Utilice 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

Por cierto, si está utilizando Postgres 9.1, no necesita repetir las columnas de SELECT a GROUP BY, por ejemplo, no necesita repetir el nombre del estudiante en GROUP BY. Simplemente puede AGRUPAR POR en la clave principal. Si quita la clave principal del alumno, debe repetir el nombre del alumno en 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');
Miguel Buen
fuente
2
Oh, Dios mío, muchas gracias por tu comentario sobre select / group, ¡es tan increíble! ¡Eso fue realmente molesto!
mrbrdo
8

Lo que entiendo es que puedes hacer algo como esto:

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

No estoy seguro. Pero tal vez algo como esto entonces:

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;

Referencia aquí

Arion
fuente
Creo que quiere una matriz pgsql, no una cadena separada por comas
ThiefMaster
0

@Michael Buen lo hizo bien. Obtuve lo que necesitaba usando array_agg.

Aquí solo un ejemplo de consulta básica en caso de que ayude a alguien:

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

Y el resultado fue 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} |


Esta publicación también me ayudó mucho: "Agrupar por" en SQL y Python Pandas . Básicamente dice que es más conveniente usar solo SQL cuando sea posible, pero que Python Pandas puede ser útil para lograr funcionalidades extra en el proceso de filtrado.

Espero que ayude

Javi
fuente