J'ai un tableau d'utilisation horaire du produit (combien de fois le produit est utilisé) -
ID (bigint)| ProductId (tinyint)| Date (int - YYYYMMDD) | Hour (tinyint)| UsageCount (int)
#|1 | 20140901 | 0 | 10
#|1 | 20140901 | 1 | 15
#|1 | 20140902 | 5 | 25
#|1 | 20140903 | 5 | 25
#|1 | 20140904 | 3 | 25
#|1 | 20140905 | 7 | 25
#|1 | 20140906 | 10 | 25
#|1 | 20140907 | 9 | 25
#|1 | 20140908 | 5 | 25
#|2 | 20140903 | 16 | 10
#|2 | 20140903 | 13 | 115
De même, j'ai les données d'utilisation de 4 produits différents (ProductId de 1 à 4) stockées pour chaque heure dans la table product_usage. Comme vous pouvez l'imaginer, il est en constante augmentation car le processus ETL nocturne vide les données de la journée précédente entière. Si un produit n'est utilisé à aucune heure de la journée, l'enregistrement de cette heure n'apparaîtra pas dans ce tableau. De même, si un produit n'est pas utilisé pendant toute la journée, il n'y aura aucun enregistrement pour cette journée dans le tableau. Je dois générer un rapport indiquant l'utilisation quotidienne et la moyenne mobile des 7 derniers jours -
Par exemple:
ProductId | Date | DailyUsage | RollingAverage
1 | 20140901 | sum of usages of that day | (Sum of usages from 20140901 through 20140826) / 7
1 | 20140901 | sum of usages of that day | (Sum of usages from 20140901 through 20140826) / 7
1 | 20140902 | sum of usages of that day | (Sum of usages from 20140902 through 20140827) / 7
2 | 20140902 | sum of usages of that day | (Sum of usages from 20140902 through 20140827) / 7
Et ainsi de suite .. Je prévois de créer une vue indexée dans SQL Server 2014. Pouvez-vous penser à une requête SQL efficace pour ce faire?
Essayer:
select x.*,
avg(dailyusage) over(partition by productid order by productid, date rows between 6 preceding and current row) as rolling_avg
from (select productid, date, sum(usagecount) as dailyusage
from tbl
group by productid, date) x
Violon:
http://sqlfiddle.com/#!6/f674a7/4/
Remplacez "avg (dailusage) over ...." par sum (plutôt que avg) si ce que vous voulez vraiment est la somme de la semaine dernière. Dans votre titre, vous dites que vous voulez la moyenne, mais plus tard vous dites que vous voulez la somme. La requête doit être la même que celle-ci, alors utilisez celle que vous voulez réellement.
Comme l'a souligné Gordon, il s'agit essentiellement de la moyenne des 6 dernières dates auxquelles le produit a été utilisé, ce qui pourrait être plus que les 6 derniers jours s'il y a des jours sans ligne pour ce produit sur la table parce qu'il n'était pas '' t utilisé du tout. Pour contourner cela, vous pouvez utiliser un tableau de dates et votre tableau de produits.
Vous devez être prudent si vous manquez des données certains jours. Si je suppose qu'il y a des données pour certains produits chaque jour, cette approche fonctionnera:
select p.productid, d.date, sum(usagecount),
sum(sum(usagecount)) over (partition by p.productid order by d.date
rows between 6 preceding and current row) as Sum7day
from (select distinct productid from hourly) p cross join
(select distinct date from hourly) d left join
hourly h
on h.productid = p.productid and h.date = p.date
group by p.productid, d.date;