Oracle: comment “groupe” sur une plage?
Si j'ai un tableau comme ceci:
pkey age
---- ---
1 8
2 5
3 12
4 12
5 22
Je peux "group by" pour obtenir un effectif de chaque âge.
select age,count(*) n from tbl group by age;
age n
--- -
5 1
8 1
12 2
22 1
Ce requêtes puis-je utiliser pour groupe par tranches d'âge?
age n
----- -
1-10 2
11-20 2
20+ 1
Je suis sur 10gR2, mais je serais intéressé par toute 11g-approches spécifiques ainsi.
Vous devez vous connecter pour publier un commentaire.
Essayer:
ceil(age/10)
est manquant dans le GROUPE PAR l'expression. Mais la direction de cette approche est mieux que @NitinMidha écrit, alors je vote cette réponse jusqu'.Ce que vous cherchez, est à la base de données pour un histogramme.
Vous aurait l'âge (ou l'âge de gamme) sur l'axe des x et le nombre n (ou la fréquence) sur l'axe des y.
Dans la forme la plus simple, on pourrait simplement compter le nombre de chaque âge distinct de la valeur comme vous avez déjà décrites:
Quand il y a trop de valeurs pour l'axe des x cependant, on peut vouloir créer des groupes (ou clusters ou des seaux). Dans votre cas, vous groupe par une constante de gamme de 10.
Nous pouvons éviter d'écrire un
WHEN ... THEN
ligne pour chaque gamme, il pourrait y avoir des centaines, si ce n'était pas une question d'âge. Au lieu de cela, l'approche par @MatthewFlaschen est préférable pour les raisons mentionnées par @NitinMidha.Maintenant nous allons créer le SQL...
Tout d'abord, nous avons besoin de diviser les âges dans la gamme de groupes de 10 comme suit:
Ceci peut être obtenu en divisant la colonne âge par 10, puis à calculer le résultat de l'ÉTAGE:
"ÉTAGE retourne le plus grand entier inférieur ou égal à celui n"
http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions067.htm#SQLRF00643
Puis nous prenons la version d'origine de SQL et de les remplacer âge avec cette expression:
C'est OK, mais nous ne pouvons pas voir la gamme, encore. Au lieu de cela on ne voit que le calcul de plancher des valeurs qui sont
0, 1, 2 ... n
.D'obtenir le véritable borne inférieure, nous avons besoin de le multiplier avec 10 de nouveau afin d'obtenir
0, 10, 20 ... n
:Nous avons aussi besoin de la limite supérieure de chaque plage est inférieur lié + 10 - 1 ou
Enfin, nous concaténer les deux dans une chaîne de caractères comme ceci:
Cela crée
'0-9', '10-19', '20-29'
etc.Maintenant notre SQL ressemble à ceci:
Enfin, appliquer une commande et de nice les alias de colonne:
Toutefois, dans des scénarios plus complexes, ces plages peuvent pas être regroupés en constante morceaux de taille 10, mais besoin de clustering dynamique.
Oracle est plus avancée de l'histogramme pour les fonctions, voir http://docs.oracle.com/cd/E16655_01/server.121/e15858/tgsql_histo.htm#TGSQL366
Crédits à @MatthewFlaschen pour son approche; j'ai seulement expliqué les détails.
Voici une solution qui crée une "gamme" de la table dans une sous-requête, puis l'utilise pour partitionner les données de la table principale:
J'ai eu de groupe de données par le nombre de transactions est apparu dans une heure. Je l'ai fait par l'extraction de l'heure de l'horodatage:
Donner de sortie:
Comme vous pouvez le voir, ce qui donne un joli moyen facile de regroupement, le nombre d'enregistrements par heure.
ajouter un age_range table et un age_range_id champ à votre table et le groupe en place.
//excuse le DDL mais vous devriez obtenir l'idée
//encore une fois excuse de la DML, mais vous devriez obtenir l'idée
Vous pouvez affiner cette idée si vous le souhaitez - ajouter from_age to_age colonnes dans la age_range table, etc - mais je vais laisser cela à vous.
espère que cela aide 🙂
Si vous utilisez Oracle 9i+, vous pourrait être en mesure d'utiliser le
NTILE
analytique de la fonction:La mise en garde à NTILE, c'est que vous ne pouvez spécifier que le nombre de partitions, pas les points de rupture eux-mêmes. Si vous avez besoin de spécifier un nombre approprié. C'est à dire: Avec 100 lignes,
NTILE(4)
attribuera 25 lignes pour chacun des quatre compartiments/partitions. Vous ne pouvez pas imbriquer les fonctions analytiques, de sorte que vous auriez à les superposer à l'aide de sous-requêtes/sous-requête d'affacturage pour obtenir granularité souhaitée. Sinon, utilisez:J'ai eu pour obtenir le nombre d'échantillons par jour. Inspiré par @Clarkey j'ai utilisé TO_CHAR pour extraire la date de l'échantillon de l'horodatage d'un ISO-8601 format de la date et utilisé que dans le GROUP BY et ORDER BY clauses. (Plus d'inspiration, j'ai aussi poster ici au cas où il est utile à d'autres.)
Mon approche:
Pouvez-vous essayer ci-dessous la solution: