Quelqu'un sait-il comment créer des requêtes de tableau croisé dans PostgreSQL?
Par exemple, j'ai le tableau suivant:
Section Status Count
A Active 1
A Inactive 2
B Active 4
B Inactive 5
Je souhaite que la requête renvoie le tableau croisé suivant:
Section Active Inactive
A 1 2
B 4 5
Est-ce possible?
Réponses:
Installez le module supplémentaire
tablefunc
une fois par base de données, qui fournit la fonctioncrosstab()
. Depuis Postgres 9.1, vous pouvez utiliserCREATE EXTENSION
pour cela:Cas de test amélioré
Formulaire simple - ne convient pas aux attributs manquants
crosstab(text)
avec 1 paramètre d'entrée:Retour:
C
: la valeur7
est remplie pour la première colonne. Parfois, ce comportement est souhaitable, mais pas pour ce cas d'utilisation.Forme sûre
crosstab(text, text)
avec 2 paramètres d'entrée:Retour:
Notez le résultat correct pour
C
.Le deuxième paramètre peut être n'importe quelle requête qui renvoie une ligne par attribut correspondant à l'ordre de la définition de colonne à la fin. Souvent, vous souhaiterez interroger des attributs distincts de la table sous-jacente comme ceci:
C'est dans le manuel.
Comme vous devez de toute façon épeler toutes les colonnes d'une liste de définitions de colonnes (à l'exception des variantes prédéfinies ), il est généralement plus efficace de fournir une courte liste dans une expression comme illustré:
crosstabN()
VALUES
Ou (pas dans le manuel):
J'ai utilisé la cotation en dollars pour faciliter la cotation.
Vous pouvez même générer des colonnes avec différents types de données avec
crosstab(text, text)
- tant que la représentation textuelle de la colonne de valeur est une entrée valide pour le type cible. De cette façon , vous pourriez avoir des attributs de différents types et de sortietext
,date
,numeric
etc. pour les attributs respectifs. Il y a un exemple de code à la fin du chapitrecrosstab(text, text)
du manuel .db <> violon ici
Exemples avancés
Pivot sur plusieurs colonnes à l'aide de Tablefunc - démontrant également les "colonnes supplémentaires" mentionnées
Alternative dynamique pour pivoter avec CASE et GROUP BY
\crosstabview
en psqlPostgres 9.6 a ajouté cette méta-commande à son terminal interactif par défaut psql . Vous pouvez exécuter la requête que vous utiliseriez comme premier
crosstab()
paramètre et la nourrir\crosstabview
(immédiatement ou à l'étape suivante). Comme:Résultat similaire à celui ci-dessus, mais il s'agit uniquement d'une fonction de représentation côté client . Les lignes en entrée sont traitées légèrement différemment, elles
ORDER BY
ne sont donc pas nécessaires. Détails pour\crosstabview
dans le manuel. Il y a plus d'exemples de code au bas de cette page.Réponse connexe sur dba.SE par Daniel Vérité (l'auteur de la fonctionnalité psql):
La réponse précédemment acceptée est obsolète.
La variante de la fonction
crosstab(text, integer)
est obsolète. Le deuxièmeinteger
paramètre est ignoré. Je cite le manuel actuel :Casting et renommage inutiles.
Il échoue si une ligne n'a pas tous les attributs. Voir la variante sûre avec deux paramètres d'entrée ci-dessus pour gérer correctement les attributs manquants.
ORDER BY
est requis sous la forme à un paramètre decrosstab()
. Le manuel:la source
In practice the SQL query should always specify ORDER BY 1,2 to ensure that the input rows are properly ordered
Vous pouvez utiliser la
crosstab()
fonction du module supplémentaire tablefunc - que vous devez installer une fois par base de données. Depuis PostgreSQL 9.1, vous pouvez utiliserCREATE EXTENSION
pour cela:Dans votre cas, je pense que cela ressemblerait à ceci:
la source
la source
sum()
, il serait préférable d'utilisermin()
oumax()
et nonELSE
qui fonctionnetext
aussi. Mais cela a des effets subtilement différents de ceuxcorosstab()
qui n'utilisent que la "première" valeur par attribut. Peu importe tant qu'il ne peut y en avoir qu'un. Enfin, les performances sont également pertinentes.crosstab()
est écrit en C et optimisé pour la tâche.ERROR: 42803: aggregate function calls may not be nested
Solution avec agrégation JSON:
la source
Désolé, ce n'est pas complet car je ne peux pas le tester ici, mais cela peut vous faire avancer dans la bonne direction. Je traduis à partir de quelque chose que j'utilise qui fait une requête similaire:
Le code à partir duquel je travaille est:
qui renverra un typeID, l'offre de prix la plus élevée et le prix le plus bas demandé et la différence entre les deux (une différence positive signifierait que quelque chose pourrait être acheté moins cher qu'il ne peut être vendu).
la source
Crosstab
est disponible sous l'tablefunc
extension. Vous devrez créer cette extension une fois pour la base de données.CRÉER UNE EXTENSION
tablefunc
;Vous pouvez utiliser le code ci-dessous pour créer un tableau croisé dynamique à l'aide du tableau croisé:
la source