2017-02-07 15 views
10

पर आधारित रनिंग कुल रीसेट करें कुल रन की गणना करने की कोशिश कर रहा हूं।एक अन्य कॉलम

;WITH cte 
    AS (SELECT id, 
       val, 
       reset_val, 
       val AS running_total 
     FROM #reset_runn_total 
     WHERE id = 1 
     UNION ALL 
     SELECT r.*, 
       CASE 
        WHEN lag(c.running_total + r.val) over(order by r.id) > lag(r.reset_val) over(order by r.id) THEN r.reset_val 
        ELSE c.running_total + r.val 
       END 
     FROM cte c 
       JOIN #reset_runn_total r 
        ON r.id = c.id + 1) 
SELECT * 
FROM cte 

जाहिर इच्छा अंतराल: लेकिन यह जब संचयी राशि एक और स्तंभ मान से अधिक

create table #reset_runn_total 
(
id int identity(1,1), 
val int, 
reset_val int 
) 

insert into #reset_runn_total 
values 
(1,10), 
(8,12),(6,14),(5,10),(6,13),(3,11),(9,8),(10,12) 

नमूना डेटा

+----+-----+-----------+ 
| id | val | reset_val | 
+----+-----+-----------+ 
| 1 | 1 |  10 | 
| 2 | 8 |  12 | 
| 3 | 6 |  14 | 
| 4 | 5 |  10 | 
| 5 | 6 |  13 | 
| 6 | 3 |  11 | 
| 7 | 9 |   8 | 
| 8 | 10 |  12 | 
+----+-----+-----------+ 

अपेक्षित परिणाम

+----+-----+-----------------+-------------+ 
| id | val | reset_val | Running_tot | 
+----+-----+-----------------+-------------+ 
| 1 | 1 | 10    |  1  | 
| 2 | 8 | 12    |  9  | --1+8 
| 3 | 6 | 14    |  15 | --1+8+6 -- greater than reset val 
| 4 | 5 | 10    |  5  | --reset 
| 5 | 6 | 13    |  11 | --5+6 
| 6 | 3 | 11    |  14 | --5+6+3 -- greater than reset val 
| 7 | 9 | 8    |  9  | --reset -- greater than reset val 
| 8 | 10 | 12    |  10  | --reset 
+----+-----+-----------------+-------------+ 

क्वेरी पुनर्स्थापित करना चाहिए नहीं मिलता पिछले मूल्य किसी भी विचार?

उत्तर

8

कोशिश झंडा पिछली पंक्ति

WITH cte 
    AS (SELECT id, 
       val, 
       reset_val, 
       val AS running_total, 
       CASE WHEN val > reset_val THEN 1 ELSE 0 END as flag 
     FROM #reset_runn_total 
     WHERE id = 1 
     UNION ALL 
     SELECT r.*, 
       CASE c.flag 
        WHEN 1 then r.val 
        ELSE c.running_total + r.val 
       END, 
       CASE WHEN CASE c.flag 
         WHEN 1 then r.val 
         ELSE c.running_total + r.val 
        END > r.reset_val 
        THEN 1 ELSE 0 END 
     FROM cte c 
       JOIN #reset_runn_total r 
        ON r.id = c.id + 1) 
SELECT * 
FROM cte 
+0

वाह .. क्या यह कुल() ओवर() विंडो का उपयोग करके हासिल किया जा सकता है? –

+0

या 'रिकर्सिव सीटीई' का उपयोग किए बिना? –

+1

ऐसा लगता है कि रिकर्सन से बचा नहीं जा सकता है ... – Serg

1

आप (पी के डिफ़ॉल्ट प्रकार) समझ बनाने के लिए की तरह इस

--- setup 
IF OBJECT_ID('tempdb..#reset_runn_total') IS NOT NULL DROP TABLE #reset_runn_total 
create table #reset_runn_total(id int identity(1,1) PRIMARY KEY, val int, reset_val int, running_sum int) 

insert into #reset_runn_total(val, reset_val) values (1,10),(8,12),(6,14),(5,10),(6,13),(3,11),(9,8),(10,12) 

--- use quirky update 
DECLARE  @running_sum INT 
      , @temp   INT 

UPDATE  #reset_runn_total 
SET   @temp = running_sum = COALESCE(@running_sum, 0) + val 
      , @running_sum = CASE WHEN @temp < reset_val THEN @temp ELSE 0 END 
OPTION  (FORCE ORDER) 

--- dump result 
SELECT * FROM #reset_runn_total 

ध्यान दें कि CLUSTERED INDEX अस्थायी मेज पर की आवश्यकता होती है एक विचित्र अद्यतन का उपयोग कर OPTION (FORCE ORDER) के लिए कोशिश कर सकते हैं ।

+0

उत्तर के लिए धन्यवाद। मुझे इसे एक से अधिक समूहों के लिए करना है। सरलीकरण के लिए मैंने केवल एक समूह के लिए नमूना डेटा जोड़ा। यह एक से अधिक समूह –

+0

के लिए काम नहीं करेगा, सुनिश्चित करें कि आप quirky अद्यतन के लिए सभी prerequsites (कम से कम 10) की जांच करें। http://www.sqlservercentral.com/articles/T-SQL/68467/ – Serg

संबंधित मुद्दे