¿Alguien sabe cómo crear consultas de tabla cruzada en PostgreSQL?
Por ejemplo tengo la siguiente tabla:
Section Status Count
A Active 1
A Inactive 2
B Active 4
B Inactive 5
Me gustaría que la consulta devuelva la siguiente tabla de referencias cruzadas:
Section Active Inactive
A 1 2
B 4 5
es posible?
Respuestas:
Instale el módulo adicional
tablefunc
una vez por base de datos, que proporciona la funcióncrosstab()
. Desde Postgres 9.1 puedes usarCREATE EXTENSION
para eso:Caso de prueba mejorado
Forma simple: no se ajusta a los atributos faltantes
crosstab(text)
con 1 parámetro de entrada:Devoluciones:
C
: el valor7
se completa para la primera columna. A veces, este comportamiento es deseable, pero no para este caso de uso.Forma segura
crosstab(text, text)
con 2 parámetros de entrada:Devoluciones:
Tenga en cuenta el resultado correcto para
C
.El segundo parámetro puede ser cualquier consulta que devuelva una fila por atributo que coincida con el orden de la definición de columna al final. A menudo querrá consultar atributos distintos de la tabla subyacente de esta manera:
Eso está en el manual.
Como debe deletrear todas las columnas en una lista de definición de columna de todos modos (excepto las variantes predefinidas ), generalmente es más eficiente proporcionar una lista corta en una expresión como la demostrada:
crosstabN()
VALUES
O (no en el manual):
Utilicé las cotizaciones en dólares para facilitar las cotizaciones.
Puede incluso columnas de salida con diferentes tipos de datos con
crosstab(text, text)
- siempre y cuando la representación de texto de la columna de valor es una entrada válida para el tipo de destino. De esta manera es posible que tenga los atributos de diferentes tipos y de salidatext
,date
,numeric
etc para los atributos respectivos. Hay un ejemplo de código al final del capítulo.crosstab(text, text)
en el manual .db <> violín aquí
Ejemplos avanzados
Pivote en múltiples columnas usando Tablefunc - también demostrando las "columnas adicionales" mencionadas
Alternativa dinámica al pivote con CASE y GROUP BY
\crosstabview
en psqlPostgres 9.6 agregó este metacomando a su terminal interactiva predeterminada psql . Puede ejecutar la consulta que usaría como primer
crosstab()
parámetro y alimentarla\crosstabview
(inmediatamente o en el siguiente paso). Me gusta:Resultado similar al anterior, pero es una característica de representación exclusiva del lado del cliente . Las filas de entrada se tratan de forma ligeramente diferente, por
ORDER BY
lo tanto, no es necesario. Detalles para\crosstabview
en el manual. Hay más ejemplos de código en la parte inferior de esa página.Respuesta relacionada en dba.SE por Daniel Vérité (el autor de la función psql):
La respuesta previamente aceptada está desactualizada.
La variante de la función
crosstab(text, integer)
está desactualizada. El segundointeger
parámetro se ignora. Cito el manual actual :Casting y cambio de nombre innecesarios.
Falla si una fila no tiene todos los atributos. Vea la variante segura con dos parámetros de entrada anteriores para manejar los atributos faltantes correctamente.
ORDER BY
se requiere en la forma de un parámetro decrosstab()
. El manual:fuente
In practice the SQL query should always specify ORDER BY 1,2 to ensure that the input rows are properly ordered
Puede usar la
crosstab()
función del módulo adicional tablefunc , que debe instalar una vez por base de datos. Desde PostgreSQL 9.1 puede usarCREATE EXTENSION
para eso:En su caso, creo que se vería así:
fuente
fuente
sum()
, sería mejor usarmin()
omax()
y no, loELSE
quetext
también funciona. Pero esto tiene efectos sutilmente diferentes quecorosstab()
, que solo usan el "primer" valor por atributo. No importa mientras solo pueda haber uno. Finalmente, el rendimiento también es relevante.crosstab()
está escrito en C y optimizado para la tarea.ERROR: 42803: aggregate function calls may not be nested
Solución con agregación JSON:
fuente
Lo siento, esto no está completo porque no puedo probarlo aquí, pero puede llevarte en la dirección correcta. Estoy traduciendo de algo que uso que hace una consulta similar:
El código con el que estoy trabajando es:
que devolverá un typeID, la oferta de precio más alto y el precio más bajo pedido y la diferencia entre los dos (una diferencia positiva significaría que algo se podría comprar por menos de lo que se puede vender).
fuente
Crosstab
La función está disponible bajo latablefunc
extensión. Tendrá que crear esta extensión una vez para la base de datos.CREAR EXTENSIÓN
tablefunc
;Puede usar el siguiente código para crear una tabla dinámica utilizando la tabla cruzada:
fuente