Moyenne pondérée en T-SQL (comme SUMPRODUCT d'Excel)
Je suis à la recherche d'un moyen de calculer une moyenne pondérée de deux lignes de données avec le même nombre de colonnes, où la moyenne s'établit comme suit (emprunt Excel notation):
(A1*B1)+(A2*B2)+...+(An*Bn)/SUM(A1:An)
La première partie reflète les mêmes fonctionnalités que d'Excel SUMPRODUCT() fonction.
Mon hic, c'est que j'ai besoin de manière dynamique spécifier la ligne qui obtient une moyenne avec des poids, et la ligne qui les pondérations viennent, et une plage de dates.
EDIT: C'est plus facile que je pensais, parce que Excel me faisait penser-je une sorte de pivot. Ma solution à ce jour est donc:
select sum(baseSeries.Actual * weightSeries.Actual) / sum(weightSeries.Actual)
from (
select RecordDate , Actual
from CalcProductionRecords
where KPI = 'Weighty'
) baseSeries inner join (
select RecordDate , Actual
from CalcProductionRecords
where KPI = 'Tons Milled'
) weightSeries on baseSeries.RecordDate = weightSeries.RecordDate
source d'informationauteur ProfK
Vous devez vous connecter pour publier un commentaire.
Quassnoi réponse montre comment faire le SumProduct, et à l'aide d'une clause where vous permettrait de restreindre par un champ de Date...
La partie la plus complexe est l'endroit où vous voulez "dynamique préciser" ce champ est [données] et ce champ est [poids]. La réponse courte est que, de façon réaliste, vous auriez à utiliser du SQL Dynamique. Quelque chose le long des lignes de:
- Créer un modèle de chaîne
- Remplacer toutes les occurrences de [tbl].de données avec les données appropriées champ
- Remplacer toutes les occurrences de [tbl].poids avec le poids approprié champ
- Exécution de la chaîne
SQL dynamique, cependant, porte ses propres généraux. Est les requêtes sont relativement peu fréquents , ou le temps d'exécution de la requête elle-même est relativement long, ce n'est pas trop grave. Si elles sont communes et court, cependant, vous pouvez remarquer que l'utilisation de sql dynamique introduit une malformation des frais généraux. (Pour ne pas mentionner faisant attention à des attaques par injection SQL, etc.)
EDIT:
Dans votre dernier exemple, vous pouvez mettre en évidence trois domaines:
Lorsque le [KPI] est de Poids "Y", puis [Réels] le Facteur de Pondération à utiliser.
Lorsque le [KPI] est "Tonnes extraites", puis [Réels] est les Données que vous voulez agréger.
Quelques questions que j'ai sont:
La raison pour laquelle je demande d'être qui vous voulez assurer la JOINDRE à vous faire est toujours de 1:1. (Vous ne voulez pas 5 chiffres Réels de rejoindre avec 5 Poids, donnant 25 resultsing records)
Indépendamment, une légère simplification de votre requête est certainement possible...
Le commentaire sur la ligne uniquement nécessaire si vous avez besoin de plus de prédicats d'assurer une relation 1:1 entre vos données et le poids.
Si vous ne pouvez pas guarnatee juste Une valeur par jour, et de ne pas avoir d'autres champs pour participer, vous pouvez modifier votre sub_query version légèrement...
Ce qui suppose le AVG de poids est valable que si il y a plusieurs poids pour le même jour.
EDIT : Quelqu'un a voté pour cela j'ai donc pensé à améliorer la réponse finale 🙂
Cela évite de le REJOINDRE et analyse la table une fois.
Il s'appuie sur le fait que
NULL
valeurs sont ignorées lors du calcul de laAVG()
.Si je comprends le problème, alors essayez cette