J'ai l'entrée suivante pour laquelle je dois calculer la somme des valeurs pour le nombre x précédent de semaines pour chaque catégorie.
Si le x est 3, la sortie ressemblerait à ceci:
Notez que la dernière valeur est 49 car elle n'a ajouté que les valeurs des deux dernières semaines à la semaine en cours depuis x = 3.
Je cherche à écrire le SQL en tant que procédure stockée et j'ai besoin d'aide sur les moyens appropriés de le faire.
Avec l'aide de @sp_BlitzErik, j'ai essayé d'utiliser LAG mais je n'ai pas pu arriver là où je devais. Voici ma requête:
SELECT category
,year
,week
,value
,(
LAG(value, 1, 0) OVER (
ORDER BY category
,year
,week
) + LAG(value, 2, 0) OVER (
ORDER BY category
,year
,week
) + value
) AS cumulative_value
FROM valuedata
Et la sortie n'est pas encore tout à fait correcte:
Sur SQL Server 2014 et 2016 1 vous pouvez utiliser une fonction WINDOW
(c'est-à-dire une clause OVER
) pour effectuer ce que vous voulez:
SELECT
category, year, week, value,
sum(value) OVER (PARTITION BY category
ORDER BY year, week
ROWS 2 PRECEDING) AS retention_value_3_weeks
FROM
t
ORDER BY
category, year, week ;
Et voici le résultat que vous obtiendrez:
Catégorie | année | semaine | valeur | retention_value_3_weeks : ---- ---: | ---: | ----: | ----------------------: a | 2016 | 1 | 5 | 5 A | 2016 | 2 | 7 | 12 A | 2016 | 3 | 8 | 20 B | 2016 | 3 | 6 | 6 B | 2016 | 4 | 15 | 21 B | 2016 | 5 | 25 | 46 C | 2016 | 3 | 25 | 25 C | 2016 | 4 | 2 | 27 C | 2016 | 5 | 21 | 48 C | 2016 | 6 | 26 | 49
Notez que le x = 3
de votre exemple est traduit en ( la ligne actuelle et la 2 preceding
ceux ).
Si, pour une raison quelconque, vous ne pouvez pas utiliser la clause OVER
, vous pouvez toujours calculer les mêmes résultats en utilisant des sous-requêtes (assez compliquées):
SELECT
category, year, week, value,
(SELECT
sum(value)
FROM
(SELECT TOP 3 /* total number of rows to consider */
value
FROM
t t2
WHERE
t2.category = t.category /* partition by category */
AND t2.week <= t.week /* current and preceding rows */
ORDER BY
year DESC, week DESC /* order by criteria */
) AS q
) AS retention_value_3_weeks
FROM
t
ORDER BY
category, year, week ;
Vérifiez tout sur dbfiddle --- (ici
Si vous souhaitez utiliser @x
au lieu de 3
, vous pouvez le faire:
DECLARE @x AS INTEGER = 3;
SELECT
category, year, week, value,
(SELECT
sum(value)
FROM
(SELECT TOP (@x) /* total number of rows to consider */
value
FROM
t t2
WHERE
t2.category = t.category /* partition by category */
AND t2.week <= t.week /* current and preceding rows */
ORDER BY
year DESC, week DESC /* order by criteria */
) AS q
) AS retention_value_3_weeks
FROM
t
ORDER BY
category, year, week ;;
dbfiddle ici
1) Impossible de tester avec SQL Server 2012 car je n'en ai pas. La documentation de MS SQL Server indique que devrait être disponible depuis la version 2008.
Voici ce que j'ai obtenu avec l'indicateur LAG de @sp_BlitzErik et le résultat est exactement ce que je voulais.
SELECT category
,year
,week
,value
,(
LAG(value, 1, 0) OVER (
PARTITION BY category ORDER BY year
,week
) + LAG(value, 2, 0) OVER (
PARTITION BY category ORDER BY year
,week
) + value
) AS cumulative_value
FROM valuedata
Mais ce n'est pas assez générique, disons pour X nombre de semaines. Veuillez poster si vous avez de meilleures réponses.
SELECT
category, year, week, value,
(SELECT
sum(t2.value)
FROM
t t1 INNER JOIN t t2
WHERE
t1.category = t2.category /* partition by category */
AND t1.week >= t.week + 2 /* current and preceding rows */
GROUP BY t1.category, t1.year, t1.week /* group by criteria */
) AS q
) AS retention_value_3_weeks
FROM
t
ORDER BY
category, year, week ;