2010-09-13 19 views
2

J'ai la requête suivante:SQL en moyenne plusieurs périodes du même ensemble de données

SELECT AVG(val) from floatTable 
WHERE tagindex IN(1,2,3,4) 
AND DateAndTime > '$first_of_year' 

Il retourne la valeur moyenne de toutes les valeurs mesurées pour les quatre balises pour l'année à ce jour. Puisque je récupère déjà ces données, comment puis-je obtenir les données depuis le premier jour du mois, depuis le début de la semaine et depuis minuit? J'ai déjà ces dates calculées comme $ first_of_month, $ first_of_week et $ minuit. J'essaie de minimiser la requête et j'espérais que quelqu'un pourrait m'aider à créer de la magie SQL pour retourner ces données dans une seule requête ou un ensemble optimisé de requêtes. Cette requête prend en moyenne 300 secondes, donc je veux le faire le moins possible.

Merci d'avance.

+0

Si vous ne voulez pas faire trop d'allers-retours à la base de données, vous pouvez simplement mettre ces moyennes dans les sous-requêtes dans une requête énorme. En ce qui concerne ma majeure en mathématiques, il me dit que les moyennes ne peuvent pas être divisées ou combinées, donc vous devez vraiment les calculer à nouveau sur différentes périodes de temps. –

+0

@Denis, voir la réponse de RedFilter. Les sous-requêtes ne nécessiteraient pas de déplacements supplémentaires dans la base de données, mais * nécessiteraient des lectures logiques supplémentaires au sein de la requête, de sorte que le temps global de la requête pourrait être jusqu'à quatre fois plus long. En ce qui concerne les moyennes, la plupart des versions de SQL omettent complètement les valeurs NULL des calculs agrégés - donc les quatre expressions différentes dans la requête de RedFilter seraient calculées correctement (car les valeurs qui ne satisfont pas les conditions seraient évaluées comme NULL). –

+1

@Mark Bannister, j'ai silencieusement admis mon faux pas au moment RedFilter posté sa réponse et immédiatement appris de lui et je voulais laisser mon commentaire pour la postérité pour apprendre de mon hypothèse rapide. –

Répondre

5
SELECT AVG(case when DateAndTime > '$first_of_year' then val end) as FirstOfYear, 
     AVG(case when DateAndTime > '$first_of_month' then val end) as FirstOfMonth, 
     AVG(case when DateAndTime > '$first_of_week' then val end) as FirstOfWeek, 
     AVG(case when DateAndTime > '$midnight' then val end) as Midnight 
from floatTable 
WHERE tagindex IN(1,2,3,4) 
    and DateAndTime > '$first_of_year' 

Pour améliorer les performances, assurez-vous que vous avez des index sur des colonnes DateAndTime et tagIndex.

+0

Cela fonctionne très bien ... comment ça se passe tellement plus vite que ma requête d'origine? – user438199

+1

Il ne devrait pas être plus rapide que la requête dans votre question, mais il ne sera probablement pas (beaucoup) plus lent, malgré l'ajout des colonnes supplémentaires dont vous avez besoin. Lorsque vous parlez de «question originale», voulez-vous dire celui de votre question ou en avez-vous un pour obtenir toutes les autres moyennes que vous vouliez? Il peut s'agir d'un problème de mise en cache: vous avez déjà exécuté une requête afin que SQL Server dispose de ces données en mémoire. –

+0

@ user438199 S'il vous plaît vérifier que vous voulez dire> = '$ first_of_year' –