Exécution de SUM dans T-SQL

Désolé pour le mauvais sujet mais je n'étais pas sûr de savoir comment l'appeler ..

J'ai une table qui ressemble à ceci:

+-----++-----+ | Id ||Count| +-----++-----+ | 1 || 1 | +-----++-----+ | 2 || 5 | +-----++-----+ | 3 || 8 | +-----++-----+ | 4 || 3 | +-----++-----+ | 5 || 6 | +-----++-----+ | 6 || 8 | +-----++-----+ | 7 || 3 | +-----++-----+ | 8 || 1 | +-----++-----+ 

J'essaye de faire un select de cette table où chaque SUM de row1 + row2 + row3 (etc) atteint 10, alors c'est un "HIT", et le count recommence encore.

Sortie demandée:

 +-----++-----++-----+ | Id ||Count|| HIT | +-----++-----++-----+ | 1 || 1 || N | Count = 1 +-----++-----++-----+ | 2 || 5 || N | Count = 6 +-----++-----++-----+ | 3 || 8 || Y | Count = 14 (over 10) +-----++-----++-----+ | 4 || 3 || N | Count = 3 +-----++-----++-----+ | 5 || 6 || N | Count = 9 +-----++-----++-----+ | 6 || 8 || Y | Count = 17 (over 10..) +-----++-----++-----+ | 7 || 3 || N | Count = 3 +-----++-----++-----+ | 8 || 1 || N | Count = 4 +-----++-----++-----+ 

Comment puis-je faire cela, et avec les meilleures performances? Je n'ai aucune idée..

Vous pouvez utiliser des requêtes récursives

S'il vous plaît noter la requête suivante en supposant que la valeur d'id sont tous dans la séquence, sinon, s'il vous plaît utilisez ROW_NUMBER() pour créer un nouvel ID

 WITH cte AS ( SELECT id, [Count], [Count] AS total_count FROM Table1 WHERE id = 1 UNION ALL SELECT t2.id,t2.[Count], CASE WHEN t1.total_count >= 10 THEN t2.[Count] ELSE t1.total_count + t2.[Count] END FROM Table1 t2 INNER JOIN cte t1 ON t2.id = t1.id + 1 ) SELECT * FROM cte ORDER BY id 

SQL Fiddle

C'est trop long pour un commentaire.

Vous ne pouvez pas le faire en utilisant les fonctions window / analytique, car les points d'arrêt ne sont pas connus à l'avance. Parfois, il est possible de calculer les points de rupture. Cependant, dans ce cas, les points de rupture dépendent d'une fonction non-linéaire des valeurs précédentes (je ne peux pas penser à un meilleur mot que "non-linéaire" en ce moment). C'est-à-dire que l'ajout de "1" à une valeur précédente a parfois un effet nul sur le calcul de la ligne en cours. Parfois, cela a un grand effet. L'implication est que le calcul doit commencer au début et parcourir datatables.

Une modification mineure au problème serait résoluble en utilisant de telles fonctions. Si le problème était, au contraire, de reporter le montant excédentaire pour chaque groupe (au lieu de recommencer la sum), le problème pourrait être résolu en utilisant des sums cumulées (et d'autres astuces).

Les requêtes récursives (fournies par d'autres) ou une opération séquentielle constituent le meilleur moyen d'aborder ce problème. Malheureusement, il n'a pas de méthode basée sur un set pour le résoudre.

J'espère vraiment que quelqu'un peut nous montrer si c'est possible de le faire en utilisant des fonctions de window directes. C'est le vrai défi.

En attendant, voici comment je le ferais en utilisant la récursivité. Cela gère les espaces dans la séquence, et gère le cas de bord de la première ligne étant déjà >= 10 .

J'ai également ajouté l'indice maxrecursion pour supprimer la limite de récursivité par défaut. Mais honnêtement, je ne sais pas si cela va fonctionner avec de plus grandes quantités de données.

 with NumberedRows as ( select Id, Cnt, row_number() over(order by id) as rn from CountTable ), RecursiveCTE as ( select Id, Cnt, rn, case when Cnt >= 10 then 0 else Cnt end as CumulativeSum, case when Cnt >= 10 then 'Y' else 'N' end as hit from NumberedRows where rn = 1 union all select n.Id, n.Cnt, n.rn, case when (n.Cnt + r.CumulativeSum) >= 10 then 0 else n.Cnt + r.CumulativeSum end as CumulativeSum, case when (n.Cnt + r.CumulativeSum) >= 10 then 'Y' else 'N' end as hit from RecursiveCTE r join NumberedRows n on n.rn = r.rn + 1 ) select Id, Cnt, hit from RecursiveCTE order by Id option (maxrecursion 0) 

SQLFiddle Demo

Que diriez-vous de cela en utilisant Totals Running:

 DECLARE @Data TABLE( Id INT ,SubTotal INT ) INSERT INTO @Data VALUES(1, 5) INSERT INTO @Data VALUES(2, 3) INSERT INTO @Data VALUES(3, 4) INSERT INTO @Data VALUES(4, 4) INSERT INTO @Data VALUES(5, 7) DECLARE @RunningTotal INT = 0 DECLARE @HitCount INT = 0 SELECT @RunningTotal = CASE WHEN @RunningTotal < 10 THEN @RunningTotal + SubTotal ELSE SubTotal END ,@HitCount = @HitCount + CASE WHEN @RunningTotal >= 10 THEN 1 ELSE 0 END FROM @Data ORDER BY Id SELECT @HitCount -- Outputs 2 

Après avoir relu la question, je vois que cela ne répond pas à la request requirejse – je vais laisser la réponse car elle peut être utile à quelqu'un qui cherche un exemple d'une solution complète pour ce type de problème qui n'a pas besoin chaque ligne étiquetée avec un Y ou un N.