2013-07-12 2 views
-1

Je ne suis pas marié à cet algorithme alors n'hésitez pas à utiliser n'importe quelle idée - cet algorithme illustre juste le problème que j'essaie de résoudre. Supposons que j'ai une table avec "RecID", "Value" et "Result". Je voudrais filtrer les valeurs de chaque ligne par rapport aux autres lignes. Ainsi, par exemple:Tricky SQL algorithme, peut-être il ya une meilleure façon

Disons que vous avez une table:

SELECT RecID, Value, Result 
INTO #temp 
FROM (
SELECT 1 as RecID, 60 as Value, NULL as result 
UNION 
SELECT 2 as RecID, -30 as Value, NULL as result 
UNION 
SELECT 4 as RecID, -200 as Value, NULL as result 
UNION 
SELECT 5 as RecID, -250 as Value, NULL as result 
UNION 
SELECT 6 as RecID, 300 as Value, NULL as result 
) a 

1) Trier cette table par COALESCE (ABS (résultat), ABS (valeur)), ABS (valeur)) dans l'ASC pour que vous obtiendrez:

RecID, Value, Result 
2,  -30, NULL    
1,  60, NULL  
4,  -200, NULL 
5,  -250, NULL 
6,  300, NULL 

2) TRAITEMENT eT ROW1 ROW2: Étant donné que les signes de la valeur sont opposées (Row1 et Row2) enlever la valeur de Row1 de Row1 et Row2 et écrivez ce qui reste à faire. Donc, enlever -30 de RecID 1 et écrire au résultat, et ajouter -30 à la valeur dans RecID 2 et écrire au résultat et trier à nouveau sur COALESCE (ABS (résultat), ABS (valeur)), ABS (valeur)) :

RecID, Value, Result 
2,  -30, 0  <-- 
1,  60, 30  <-- 
4,  -200, NULL 
5,  -250, NULL 
6,  300, NULL 

3) TRAITEMENT ROW2 eT row3: Étant donné que les signes de la valeur sont opposées (Row2 et row3) enlever 30 (le résultat de recid 1) à partir de rECID 4 et écrire à entraîner, enlever ce même 30 de RecID 1 et écrire au résultat et trier à nouveau sur COALESCE (ABS (résultat), ABS (valeur)), ABS (valeur)):

RecID, Value, Result 
2,  -30, 0 
1,  60, 0  <-- 
4,  -200, -170  <-- 
5,  -250, NULL 
6,  300, NULL 

4) TRAITEMENT Row3 ET ROW4: Étant donné que les signes de la valeur sont les mêmes pour (Row3 et Row4) rien ne doit être fait copier la valeur pour résultat et trier à nouveau sur COALESCE (ABS (résultat), ABS (valeur)), ABS (valeur)):

RecID, Value, Result 
2,  -30, 0 
1,  60, 0 
4,  -200, -170  <-- 
5,  -250, -250  <-- 
6,  300, NULL 

5) TRAITEMENT eT row3 ROW4: Étant donné que les signes de la valeur sont opposées (row3 et Row4) Otez -170 (résultat de recid 4) à partir de 300 et écrire au résultat, trier à nouveau le COALESCE (ABS (résultat), ABS (valeur)), ABS (valeur)) et obtenez:

RecID, Value, Result 
2,  -30, 0 
1,  60, 0 
4,  -200, 0  <--  
6,  300, 130  <-- 
5,  -250, -250 

6) TRAITEMENT ROW4 ET ROW5: Étant donné que les signes de la valeur sont opposées (Row4 et Row5) Otez 130 (résultat de 6 recid) de -250 et trier à nouveau sur COALESCE (ABS (résultat), ABS (valeur)), ABS (valeur)) et obtenez:

RecID, Value, Result 
2,  -30, 0 
1,  60, 0 
4,  -200, 0 
6,  300, 0   <-- 
5,  -250, -120  <-- 

Rien de plus ne peut être compensé puisque les dernières valeurs avec des signes opposés ont déjà été compensées.

Je ne sais pas trop comment écrire quelque chose comme ça.

+0

Souhaitez-vous que toutes les lignes soient mises à jour pour refléter le résultat de 7) ou recherchez-vous autre chose? –

+0

Donc, fondamentalement, vous voulez les additionner, mettre la somme dans l'une des rangées et mettre les autres à zéro? – RBarryYoung

+0

@rbarryyoung - Si vous n'aviez pas la dernière ligne, vous finiriez à l'étape 4 et vous auriez 2 lignes non nulles. – Denis

Répondre

1

Algorithme bien présenté.Le tout brûle à:

SELECT sum(values) AS result FROM #temp; 

Renvoie . Ou y a-t-il autre chose que vous voulez réaliser?

+0

Bien essayé, mais si vous omettez la dernière ligne de la table #temp, la table de l'étape 4 doit être retournée. -170 serait laissé pour RecId 4, et -250 pour RecID 5. Il ne devrait pas être juste 1 valeur, il devrait être un ensemble de rangées avec des valeurs qui ne pourraient pas être compensées complètement. – Denis