Transposer les lignes et les colonnes (un.k.un. pivot) uniquement avec un minimum de COUNT()?
Voici ma table 'tab_test':
year animal price
2000 kittens 79
2000 kittens 93
2000 kittens 100
2000 puppies 15
2000 puppies 32
2001 kittens 31
2001 kittens 17
2001 puppies 65
2001 puppies 48
2002 kittens 84
2002 kittens 86
2002 puppies 15
2002 puppies 95
2003 kittens 62
2003 kittens 24
2003 puppies 36
2003 puppies 41
2004 kittens 65
2004 kittens 85
2004 puppies 58
2004 puppies 95
2005 kittens 45
2005 kittens 25
2005 puppies 15
2005 puppies 35
2006 kittens 50
2006 kittens 80
2006 puppies 95
2006 puppies 49
2007 kittens 40
2007 kittens 19
2007 puppies 81
2007 puppies 38
2008 kittens 37
2008 kittens 51
2008 puppies 29
2008 puppies 72
2009 kittens 84
2009 kittens 26
2009 puppies 49
2009 puppies 34
2010 kittens 75
2010 kittens 96
2010 puppies 18
2010 puppies 26
2011 kittens 35
2011 kittens 21
2011 puppies 90
2011 puppies 18
2012 kittens 12
2012 kittens 23
2012 puppies 74
2012 puppies 79
Voici un code qui transpose les lignes et les colonnes et j'obtiens donc un moyen pour les "chatons" et "chiots':
SELECT
year,
AVG(CASE WHEN animal = 'kittens' THEN price END) AS "kittens",
AVG(CASE WHEN animal = 'puppies' THEN price END) AS "puppies"
FROM tab_test
GROUP BY year
ORDER BY year;
La sortie pour le code ci-dessus est:
year kittens puppies
2000 90.6666666666667 23.5
2001 24.0 56.5
2002 85.0 55.0
2003 43.0 38.5
2004 75.0 76.5
2005 35.0 25.0
2006 65.0 72.0
2007 29.5 59.5
2008 44.0 50.5
2009 55.0 41.5
2010 85.5 22.0
2011 28.0 54.0
2012 17.5 76.5
Ce que j'aimerais c'est un tableau comme le second, mais il ne serait que de contenir des éléments qui avaient un COUNT()
d'au moins 3 dans la première table. En d'autres termes, l'objectif est d'avoir ce de sortie:
year kittens
2000 90.6666666666667
Il y avait au moins 3 cas de "chaton" dans le premier tableau.
Est-ce possible dans PostgreSQL?
OriginalL'auteur user1626730 | 2012-10-31
Vous devez vous connecter pour publier un commentaire.
Voici une alternative à @bluefeet la suggestion de, qui est un peu similaire, mais évite de le rejoindre (au lieu de cela, le haut niveau de regroupement est appliqué à l'ensemble de résultats groupés):
OriginalL'auteur Andriy M
CASE
Si votre cas est simple, comme l'a démontré, un
CASE
déclaration:N'a pas d'importance si vous utilisez
sum()
,max()
oumin()
comme fonction d'agrégation dans la requête externe. Ils ont tous la même valeur dans ce cas.SQL Violon
crosstab()
Avec plus de catégories, il sera plus simple avec un
crosstab()
requête. Cela devrait également être plus rapide pour les grandes tables.Vous devez installer le module supplémentaire tablefunc (une fois par base de données). Depuis Postgres 9.1, c'est aussi simple que:
Détails dans cette réponse:
Pas sqlfiddle pour celui-ci car le site ne permet pas de modules supplémentaires.
De référence
Pour vérifier mes demandes, j'ai couru un rapide test avec près de réel données dans ma petite base de données de test. PostgreSQL 9.1.6. Test avec
EXPLAIN ANALYZE
, mieux de 10:Configuration de Test avec 10020 lignes:
Résultats:
@bluefeet
Total runtime: 95.401 ms
@wildplasser (des résultats différents, comprend des lignes avec
count <= 3
)Total runtime: 64.497 ms
@Andreiy (+
ORDER BY
)& @Erwin1 -
CASE
(à la fois effectuer sur le même)Total runtime: 39.105 ms
@Erwin2 -
crosstab()
Total runtime: 17.644 ms
Largement proportionnel (mais peu importe), les résultats avec seulement 20 lignes. Seul @wildplasser du CCE a plus de frais généraux et des pointes un peu.
Avec plus d'une poignée de lignes,
crosstab()
rapidement prend la tête.@Andreiy de la requête effectue sur la même que ma version simplifiée, la fonction d'agrégation à l'extérieur de la
SELECT
(min()
,max()
,sum()
) ne fait pas de différence mesurable (juste deux lignes par groupe).Tout comme prévu, pas de surprises, prendre ma configuration et l'essayer @home.
Les deux sont plus lents? Le
CASE
version devrait être aussi rapide ou plus rapide - à l'exception de l'manquantORDER BY
dans @Andriy de la version. Hmm ... peut-êtresum()
est plus lent quemax()
.. mais ne devrait guère être pertinentes. Lecrosstab()
version serait plus rapide pour les cas plus complexes / les grandes tables.Eh bien, le premier était entre 100-200ms sur SQLfiddle, tandis que @AndriyM l'a été entre 1-10ms. De même, le tableau croisé info sera probablement utile pour moi dans l'avenir, comme moi je ne plan sur la création des tableaux croisés.
Ces chiffres sont des artefacts de mesure. Avec un petit ensemble de données, vous pouvez à peine obtenir fiable timings sur sqlfiddle. J'ai couru un rapide test en local pour vérifier mes revendications et de l'ajouter à ma réponse.
Ah, je vois. Dans ce cas, je vais essayer tous ces codes. Je vous remercie.
OriginalL'auteur Erwin Brandstetter
Est-ce que vous êtes à la recherche pour:
Voir SQL jouer avec la Démo
OriginalL'auteur Taryn
OriginalL'auteur wildplasser