Toutes mes excuses pour le mauvais titre, je ne savais pas ce qui serait un bon titre pour ça.
Il s'agit actuellement (vue simplifiée des) données avec lesquelles je travaille
Agent | Commission
---------|------------
Smith | 100
Neo | 200
Morpheus | 300
Je dois calculer le pourcentage de la commission totale dont chaque agent est responsable.
Ainsi, pour l'agent Smith, le pourcentage serait calculé comme suit: (Agent Smith's commission / Sum(commission)*100
Donc, mes données attendues seraient
Agent | Commission | % Commission
---------|---------------|---------------
Smith | 100 | 17
Neo | 200 | 33
Morpheus | 300 | 50
J'ai une fonction de restitution de la commission pour chaque agent. J'ai une autre fonction renvoyant le pourcentage comme (Commission/Sum(Commission))*100
. Le problème est que l' Sum(commission)
on calcule pour chaque ligne, et étant donné que cette requête serait exécutée sur un entrepôt de données, l'ensemble de données serait plutôt volumineux (actuellement, c'est juste un peu moins de 2000 enregistrements) et très honnêtement, une mauvaise approche (IMO ).
Existe-t-il un moyen de Sum(Commission)
ne pas calculer pour chaque ligne récupérée?
Je pensais à quelque chose sur les lignes d'une requête en 2 parties, la première partie récupérerait le sum(commission)
dans une variable / type de package et la deuxième partie ferait référence à cette valeur pré-calculée, mais je ne sais pas comment je peux y parvenir.
Je suis limité à l'utilisation de SQL et j'exécute sur Oracle 10g R2.
la source
Réponses:
Vous recherchez le
analytical function
ratio_to_reportla source
Pour renvoyer tous les agents avec leurs commissions et pourcentages de commission, utilisez une fonction analytique sans clause analytique afin que la partition soit sur toute la table:
Comme je l'ai appris de René Nyffenegger (+1), la fonction ratio_to_report resserre cette syntaxe.
L'utilisation d'un package pour stocker le SUM de la Commission impliquerait PL / SQL, que vous avez spécifiquement exclu en indiquant que vous souhaitez une solution SQL, mais puisque vous utilisez déjà des fonctions, je suppose que votre intention n'était pas d'exclure PL / SQL. Si tel est le cas, la solution de package peut vous aider, mais cela dépend du fonctionnement de votre application.
Lorsque votre session est créée et appelle la fonction dans le package pour obtenir la commission, il y a un appel implicite au constructeur des packages qui pourrait obtenir la somme et la stocker. Ensuite, vous pouvez référencer la somme stockée dans votre fonction get commission et elle ne devra effectuer la somme qu'une seule fois. Bien sûr, dès que vous appelez la fonction à partir d'une session différente, la somme sera à nouveau calculée. En outre, appeler la fonction pour chaque agent serait considérablement moins efficace que d'appeler une instruction SQL pour tous les agents si votre application pouvait être conçue de cette manière.
Vous souhaiterez peut-être envisager de transformer votre fonction en une procédure qui renvoie un curseur pour la requête ci-dessus ou peut-être avoir une fonction qui renvoie les résultats de la requête sous la forme d'un ensemble de résultats en pipeline.
Exemples de données:
la source
Vous pouvez essayer la requête suivante, la somme (commission) ne sera calculée qu'une seule fois:
la source
la source