SQL सर्वर में चल रहे कुल की गणना करें


170

निम्नलिखित तालिका की कल्पना कीजिए (कहा जाता है TestTable):

id     somedate    somevalue
--     --------    ---------
45     01/Jan/09   3
23     08/Jan/09   5
12     02/Feb/09   0
77     14/Feb/09   7
39     20/Feb/09   34
33     02/Mar/09   6

मैं एक क्वेरी चाहूँगा जो दिनांक क्रम में चल रहे कुल को लौटाए, जैसे:

id     somedate    somevalue  runningtotal
--     --------    ---------  ------------
45     01/Jan/09   3          3
23     08/Jan/09   5          8
12     02/Feb/09   0          8
77     14/Feb/09   7          15  
39     20/Feb/09   34         49
33     02/Mar/09   6          55

मुझे पता है कि SQL Server 2000/2005/2008 में ऐसा करने के विभिन्न तरीके हैं ।

मुझे इस तरह की विधि में विशेष रूप से दिलचस्पी है जो समुच्चय-कथन-चाल का उपयोग करता है:

INSERT INTO @AnotherTbl(id, somedate, somevalue, runningtotal) 
   SELECT id, somedate, somevalue, null
   FROM TestTable
   ORDER BY somedate

DECLARE @RunningTotal int
SET @RunningTotal = 0

UPDATE @AnotherTbl
SET @RunningTotal = runningtotal = @RunningTotal + somevalue
FROM @AnotherTbl

... यह बहुत ही कुशल है, लेकिन मैंने सुना है कि इसके आस-पास के मुद्दे हैं क्योंकि आप जरूरी गारंटी नहीं दे सकते कि UPDATEकथन सही क्रम में पंक्तियों को संसाधित करेगा। हो सकता है कि हम उस मुद्दे के बारे में कुछ निश्चित जवाब पा सकें।

लेकिन शायद ऐसे और भी तरीके हैं जिनसे लोग सुझाव दे सकते हैं?

संपादित करें: अब सेटअप के साथ एक SqlFiddle और ऊपर 'अद्यतन चाल' उदाहरण के साथ


blogs.msdn.com/sqltips/archive/2005/07/20/441053.aspx अपने अपडेट द्वारा एक आदेश जोड़ें ... सेट करें और आपको एक गारंटी मिलती है।
शमौन डी

लेकिन आदेश द्वारा अद्यतन विवरण पर लागू नहीं किया जा सकता ... क्या यह हो सकता है?
कोडुलिक

इसके अलावा sqlperformance.com/2012/07/t-sql-queries/running-totals देखें, खासकर यदि आप SQL Server 2012 का उपयोग कर रहे हैं।
हारून बर्ट्रेंड

जवाबों:


133

अद्यतन करें , यदि आप SQL Server 2012 देख रहे हैं: https://stackoverflow.com/a/10309947

समस्या यह है कि ओवर क्लॉज का SQL सर्वर कार्यान्वयन कुछ सीमित है

Oracle (ANSI-SQL) आपको ऐसा करने की अनुमति देता है:

 SELECT somedate, somevalue,
  SUM(somevalue) OVER(ORDER BY somedate 
     ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) 
          AS RunningTotal
  FROM Table

SQL सर्वर आपको इस समस्या का कोई साफ समाधान नहीं देता है। मेरा पेट मुझे बता रहा है कि यह उन दुर्लभ मामलों में से एक है जहां एक कर्सर सबसे तेज़ है, हालांकि मुझे बड़े परिणामों पर कुछ बेंचमार्किंग करनी होगी।

अद्यतन चाल आसान है, लेकिन मुझे इसकी काफी नाजुक लगती है। ऐसा लगता है कि यदि आप एक पूर्ण तालिका अपडेट कर रहे हैं तो यह प्राथमिक कुंजी के क्रम में आगे बढ़ेगा। इसलिए यदि आप अपनी तिथि को एक प्राथमिक कुंजी के रूप में सेट करते हैं तो आप probablyसुरक्षित रहेंगे । लेकिन आप एक अनिर्दिष्ट SQL Server कार्यान्वयन विवरण पर भरोसा कर रहे हैं (यह भी कि यदि क्वेरी समाप्त होती है, तो मुझे आश्चर्य होता है कि मुझे क्या करना होगा, देखें: MAXDOP):

पूर्ण कार्य नमूना:

drop table #t 
create table #t ( ord int primary key, total int, running_total int)

insert #t(ord,total)  values (2,20)
-- notice the malicious re-ordering 
insert #t(ord,total) values (1,10)
insert #t(ord,total)  values (3,10)
insert #t(ord,total)  values (4,1)

declare @total int 
set @total = 0
update #t set running_total = @total, @total = @total + total 

select * from #t
order by ord 

ord         total       running_total
----------- ----------- -------------
1           10          10
2           20          30
3           10          40
4           1           41

आपने एक बेंचमार्क के लिए कहा यह निम्नता है।

ऐसा करने का सबसे तेज़ सुरक्षित तरीका कर्सर होगा, यह क्रॉस-ज्वाइन के सहसंबद्ध उप-क्वेरी की तुलना में तेज़ी का परिमाण है।

सबसे तेज़ तेज़ तरीका UPDATE चाल है। इसके साथ मेरी एकमात्र चिंता यह है कि मैं निश्चित नहीं हूं कि सभी परिस्थितियों में अद्यतन रैखिक रूप से आगे बढ़ेगा। स्पष्ट रूप से ऐसा कहने वाले प्रश्न में कुछ भी नहीं है।

निचला रेखा, उत्पादन कोड के लिए मैं कर्सर के साथ जाऊंगा।

परीक्षण डेटा:

create table #t ( ord int primary key, total int, running_total int)

set nocount on 
declare @i int
set @i = 0 
begin tran
while @i < 10000
begin
   insert #t (ord, total) values (@i,  rand() * 100) 
    set @i = @i +1
end
commit

टेस्ट 1:

SELECT ord,total, 
    (SELECT SUM(total) 
        FROM #t b 
        WHERE b.ord <= a.ord) AS b 
FROM #t a

-- CPU 11731, Reads 154934, Duration 11135 

टेस्ट 2:

SELECT a.ord, a.total, SUM(b.total) AS RunningTotal 
FROM #t a CROSS JOIN #t b 
WHERE (b.ord <= a.ord) 
GROUP BY a.ord,a.total 
ORDER BY a.ord

-- CPU 16053, Reads 154935, Duration 4647

टेस्ट 3:

DECLARE @TotalTable table(ord int primary key, total int, running_total int)

DECLARE forward_cursor CURSOR FAST_FORWARD 
FOR 
SELECT ord, total
FROM #t 
ORDER BY ord


OPEN forward_cursor 

DECLARE @running_total int, 
    @ord int, 
    @total int
SET @running_total = 0

FETCH NEXT FROM forward_cursor INTO @ord, @total 
WHILE (@@FETCH_STATUS = 0)
BEGIN
     SET @running_total = @running_total + @total
     INSERT @TotalTable VALUES(@ord, @total, @running_total)
     FETCH NEXT FROM forward_cursor INTO @ord, @total 
END

CLOSE forward_cursor
DEALLOCATE forward_cursor

SELECT * FROM @TotalTable

-- CPU 359, Reads 30392, Duration 496

टेस्ट 4:

declare @total int 
set @total = 0
update #t set running_total = @total, @total = @total + total 

select * from #t

-- CPU 0, Reads 58, Duration 139

1
धन्यवाद। इसलिए आपका कोड नमूना प्रदर्शित करना है कि यह प्राथमिक कुंजी के क्रम में योग करेगा, मुझे लगता है। यह जानना दिलचस्प होगा कि क्या बड़े डेटा सेट के लिए शापर्स अभी भी जॉइनर्स की तुलना में अधिक कुशल हैं।
कोडुलिक

1
मैंने अभी CTE @Martin का परीक्षण किया, कुछ भी अपडेट ट्रिक के करीब नहीं आया - कर्सर रीड पर कम लगता है। यहाँ एक प्रोफाइल ट्रेस i.stack.imgur.com/BbZq3.png है
सैम सैफ्रन


1
इस जवाब में डाले गए सभी काम के लिए +1 - मुझे अद्यतन विकल्प पसंद है; क्या इस अद्यतन स्क्रिप्ट में एक विभाजन बनाया जा सकता है? उदाहरण के लिए, यदि कोई अतिरिक्त फ़ील्ड "कार कलर" है, तो क्या यह स्क्रिप्ट प्रत्येक "कार कलर" पार्टीशन के भीतर चल रहे कुल योग को लौटा सकती है?
Whytheq

2
प्रारंभिक (ओरेकल (और एएनएसआई-एसक्यूएल)) उत्तर अब एसक्यूएल सर्वर 2017 में काम करता है। धन्यवाद, बहुत सुरुचिपूर्ण!
दानीदेव


40

जबकि सैम सैफ्रन ने इस पर बहुत काम किया, फिर भी उन्होंने इस समस्या के लिए पुनरावर्ती सामान्य तालिका अभिव्यक्ति कोड प्रदान नहीं किया । और हमारे लिए जो SQL Server 2008 R2 के साथ काम कर रहे हैं और Denali नहीं, यह अभी भी सबसे तेज़ तरीके से चल रहा है, यह 100000 पंक्तियों के लिए मेरे कार्य कंप्यूटर पर कर्सर से लगभग 10 गुना तेज़ है, और यह इनलाइन क्वेरी भी है।
इसलिए, यहां यह है (मैं मान रहा हूं कि ordतालिका में एक स्तंभ है और यह अंतराल के बिना अनुक्रमिक संख्या है, तेजी से प्रसंस्करण के लिए इस संख्या पर अद्वितीय बाधा भी होनी चाहिए):

;with 
CTE_RunningTotal
as
(
    select T.ord, T.total, T.total as running_total
    from #t as T
    where T.ord = 0
    union all
    select T.ord, T.total, T.total + C.running_total as running_total
    from CTE_RunningTotal as C
        inner join #t as T on T.ord = C.ord + 1
)
select C.ord, C.total, C.running_total
from CTE_RunningTotal as C
option (maxrecursion 0)

-- CPU 140, Reads 110014, Duration 132

sql fiddle demo

अद्यतन मैं भी चर या quirky अद्यतन के साथ इस अद्यतन के बारे में उत्सुक था । इसलिए आमतौर पर यह ठीक काम करता है, लेकिन हम कैसे सुनिश्चित कर सकते हैं कि यह हर बार काम करता है? ठीक है, यहाँ एक छोटी सी चाल है (इसे यहाँ पाया - http://www.sqlservercentral.com/Forums/Topic802558-203-21.aspx#bm981258 ) - आप बस वर्तमान और पिछले की जांच ordकरते हैं और 1/0मामले में असाइनमेंट का उपयोग करते हैं जो वे से अलग हैं आप उम्मीद कर रहे हैं:

declare @total int, @ord int

select @total = 0, @ord = -1

update #t set
    @total = @total + total,
    @ord = case when ord <> @ord + 1 then 1/0 else ord end,
    ------------------------
    running_total = @total

select * from #t

-- CPU 0, Reads 58, Duration 139

अगर मैंने देखा है कि आपके टेबल पर उचित क्लस्टर इंडेक्स / प्राइमरी की है (हमारे मामले में यह इंडेक्स होगा ord_id) अपडेट हर समय एक रेखीय तरीके से आगे बढ़ेगा (शून्य से विभाजित नहीं हुआ)। उस ने कहा, यह आपको तय करना है कि क्या आप इसे उत्पादन कोड में उपयोग करना चाहते हैं :)

अपडेट 2 मैं इस उत्तर को लिंक कर रहा हूं, क्योंकि इसमें quirky अपडेट की अविश्वसनीयता के बारे में कुछ उपयोगी जानकारी शामिल है - nvarchar कंक्रीटिंग / इंडेक्स / nvarchar (अधिकतम) अकथनीय व्यवहार


6
यह उत्तर अधिक मान्यता के योग्य है (या हो सकता है कि इसमें कुछ दोष हो जो मुझे दिखाई नहीं देते?)
user1068352

क्रमिक संख्या होनी चाहिए ताकि आप ord = ord + 1 में शामिल हो सकें और कभी-कभी इसे थोड़ा और काम करने की आवश्यकता होती है। लेकिन वैसे भी, SQL 2008 R2 पर मैं इस समाधान का उपयोग कर रहा हूं
रोमन पाकर

+1 SQLServer2008R2 पर मैं पुनरावर्ती CTE के साथ दृष्टिकोण पसंद करता हूं। FYI करें, तालिकाओं के लिए मान ज्ञात करने के लिए, जो अंतराल मैं एक सह-संबद्ध उप-क्वेरी का उपयोग करने की अनुमति देता है। यह क्वेरी sqlfiddle.com/# -3
Aleksandr Fedorenko

2
उस स्थिति के लिए जहां आपके पास पहले से ही अपने डेटा के लिए एक अध्यादेश है और आप SQL 2008 R2 पर संक्षिप्त (गैर कर्सर) सेट आधारित समाधान की तलाश में हैं, यह एकदम सही प्रतीत होता है।
Nick.McDarten 1

1
प्रत्येक चलने वाली कुल क्वेरी में एक सहायक क्षेत्र नहीं होगा जो कि सन्निहित हो। कभी-कभी आपके पास एक डेटाटाइम फ़ील्ड होता है, या रिकॉर्ड को सॉर्ट के बीच से हटा दिया जाता है। यही कारण है कि यह अधिक बार इस्तेमाल नहीं किया जा सकता है।
रूबेन

28

SQL 2005 में APPLY ऑपरेटर और इसके लिए उच्च कार्य:

select
    t.id ,
    t.somedate ,
    t.somevalue ,
    rt.runningTotal
from TestTable t
 cross apply (select sum(somevalue) as runningTotal
                from TestTable
                where somedate <= t.somedate
            ) as rt
order by t.somedate

5
छोटे डेटासेट के लिए बहुत अच्छी तरह से काम करता है। एक नकारात्मक पक्ष यह है कि आपके पास आंतरिक और बाहरी क्वेरी पर समान होने की संभावना है।
Sire

चूँकि मेरी कुछ तारीखें बिल्कुल वैसी ही थीं (एक सेकंड के अंश तक) मुझे जोड़ना था: row_number () over (txndate द्वारा आदेश) आंतरिक और बाहरी तालिका में और कुछ यौगिक सूचक इसे चलाने के लिए। चालाक / सरल समाधान। बीटीडब्लू, परीक्षण किया गया क्रॉस उपकुंजी के खिलाफ लागू होता है ... यह थोड़ा तेज है।
pghcpa

यह बहुत साफ है और छोटे डेटा सेट के साथ अच्छी तरह से काम करता है; तेजी से पुनरावर्ती CTE
jtate

यह अच्छा समाधान है और साथ ही (छोटे डेटा सेट के लिए), लेकिन आपको यह भी ध्यान रखना होगा कि यह किसी विशेष स्तंभ के अद्वितीय होने का तात्पर्य है
रोमन

11
SELECT TOP 25   amount, 
    (SELECT SUM(amount) 
    FROM time_detail b 
    WHERE b.time_detail_id <= a.time_detail_id) AS Total FROM time_detail a

आप आंतरिक चयन कथन पर तुलना में उपयोग करने के लिए एक मनमाना कॉलम बनाने के लिए ROW_NUMBER () फ़ंक्शन और एक अस्थायी तालिका का उपयोग भी कर सकते हैं।


1
यह वास्तव में अक्षम है ... लेकिन फिर SQL सर्वर में ऐसा करने का कोई वास्तविक साफ तरीका नहीं है
सैम केसर

बिल्कुल यह अक्षम है - लेकिन यह काम करता है और सही या गलत क्रम में निष्पादित के लिए कुछ है या नहीं इसका कोई सवाल ही नहीं है।
सैम ऐक्स

धन्यवाद, इसके वैकल्पिक उत्तर होने के लिए उपयोगी है, और कुशल समीक्षकों के लिए भी उपयोगी है
कोडुलिक

7

एक सहसंबद्ध उप-क्वेरी का उपयोग करें। बहुत सरल, यहाँ आप चलते हैं:

SELECT 
somedate, 
(SELECT SUM(somevalue) FROM TestTable t2 WHERE t2.somedate<=t1.somedate) AS running_total
FROM TestTable t1
GROUP BY somedate
ORDER BY somedate

कोड बिल्कुल सही नहीं हो सकता है, लेकिन मुझे यकीन है कि विचार है।

यदि कोई तिथि एक से अधिक बार दिखाई देती है, तो ग्रुप बीई एक बार परिणाम सेट में आप इसे देखना चाहते हैं।

यदि आपको बार-बार तारीखें देखने में कोई आपत्ति नहीं है, या आप मूल मूल्य और आईडी देखना चाहते हैं, तो निम्नलिखित वह है जो आप चाहते हैं:

SELECT 
id,
somedate, 
somevalue,
(SELECT SUM(somevalue) FROM TestTable t2 WHERE t2.somedate<=t1.somedate) AS running_total
FROM TestTable t1
ORDER BY somedate

धन्यवाद ... सरल बहुत अच्छा था। प्रदर्शन के लिए जोड़ने के लिए एक सूचकांक था, लेकिन यह काफी सरल था, (डेटाबेस इंजन ट्यूनिंग सलाहकार से सिफारिशों में से एक ले रहा है;), और फिर यह एक शॉट की तरह भाग गया।
डग_इवीसन

5

आप यह भी निरूपित कर सकते हैं - एक ही तालिका में चल रहे योगों की दुकान:

http://sqlblog.com/blogs/alexander_kuznetsov/archive/2009/01/23/denormalizing-to-enforce-business-rules-running-totals.aspx

किसी भी अन्य समाधान की तुलना में चयन बहुत तेजी से काम करता है, लेकिन संशोधन धीमा हो सकता है


4

मान लें कि विंडो SQL Server 2008 पर काम करता है जैसे यह कहीं और करता है (कि मैंने कोशिश की है), इसे दे दो:

select testtable.*, sum(somevalue) over(order by somedate)
from testtable
order by somedate;

MSDN का कहना है कि यह SQL Server 2008 में उपलब्ध है (और शायद 2005 तक भी?) लेकिन मेरे पास इसे आज़माने के लिए कोई उदाहरण नहीं है।

संपादित करें: ठीक है, जाहिरा तौर पर SQL सर्वर एक विंडो विनिर्देश ("OVER (...)") को "विभाजन BY" निर्दिष्ट किए बिना नहीं देता है (परिणाम को समूहों में विभाजित करता है, लेकिन समूह BY के तरीके से कुल मिलाकर नहीं)। कष्टप्रद- MSDN सिंटैक्स संदर्भ बताता है कि इसका वैकल्पिक, लेकिन मेरे पास फिलहाल SqlServer 2000 उदाहरण हैं।

क्वेरी मैंने Oracle 10.2.0.3.0 और PostgreSQL 8.4-बीटा दोनों में काम की है। तो एमएस को बताओ;)


2
SUM के साथ OVER का उपयोग इस मामले में काम नहीं करेगा ताकि कुल रनिंग दे सके। SUM के साथ उपयोग किए जाने पर OVER क्लॉज़ ORDER BY को स्वीकार नहीं करता है। आपको पार्टिशन बाय का उपयोग करना होगा, जो कुल योग चलाने के लिए काम नहीं करेगा।
सैम ऐक्स

धन्यवाद, यह वास्तव में उपयोगी है कि यह क्यों काम नहीं करता है। araqnid शायद आप अपने उत्तर को यह समझाने के लिए संपादित कर सकते हैं कि इसका विकल्प क्यों नहीं है
कोडुलिक


यह वास्तव में मेरे लिए काम करता है, क्योंकि मुझे विभाजन की आवश्यकता है - इसलिए भले ही यह सबसे लोकप्रिय उत्तर नहीं है, लेकिन यह SQL में RT के लिए मेरी समस्या का सबसे आसान समाधान है।
विलियम एमबी

मेरे पास मेरे साथ MSSQL 2008 नहीं है, लेकिन मुझे लगता है कि आप शायद विभाजन का चयन कर सकते हैं (चयन शून्य) और विभाजन समस्या के आसपास हैक कर सकते हैं। या उसके साथ एक 1 partitionmeविभाजन बनाएँ और उसके द्वारा विभाजन करें। इसके अलावा, रिपोर्ट करते समय वास्तविक जीवन स्थितियों में विभाजन की आवश्यकता होती है।
14 सितंबर

4

यदि आप ऊपर Sql सर्वर 2008 R2 का उपयोग कर रहे हैं। फिर, यह सबसे छोटा तरीका होगा;

Select id
    ,somedate
    ,somevalue,
LAG(runningtotal) OVER (ORDER BY somedate) + somevalue AS runningtotal
From TestTable 

अंतराल का उपयोग पिछली पंक्ति मान प्राप्त करने के लिए किया जाता है। आप अधिक जानकारी के लिए google कर सकते हैं।

[1]:


1
मेरा मानना ​​है कि LAG केवल SQL सर्वर 2012 और उससे ऊपर (2008 में नहीं) में मौजूद है
AaA

1
LAG () का उपयोग करने से सुधार नहीं होता है, SUM(somevalue) OVER(...) जो मुझे बहुत साफ लगता है
Used_By_Already

2

मेरा मानना ​​है कि नीचे चल रहे सरल INNER JOIN ऑपरेशन का उपयोग करके एक रनिंग टोटल हासिल किया जा सकता है।

SELECT
     ROW_NUMBER() OVER (ORDER BY SomeDate) AS OrderID
    ,rt.*
INTO
    #tmp
FROM
    (
        SELECT 45 AS ID, CAST('01-01-2009' AS DATETIME) AS SomeDate, 3 AS SomeValue
        UNION ALL
        SELECT 23, CAST('01-08-2009' AS DATETIME), 5
        UNION ALL
        SELECT 12, CAST('02-02-2009' AS DATETIME), 0
        UNION ALL
        SELECT 77, CAST('02-14-2009' AS DATETIME), 7
        UNION ALL
        SELECT 39, CAST('02-20-2009' AS DATETIME), 34
        UNION ALL
        SELECT 33, CAST('03-02-2009' AS DATETIME), 6
    ) rt

SELECT
     t1.ID
    ,t1.SomeDate
    ,t1.SomeValue
    ,SUM(t2.SomeValue) AS RunningTotal
FROM
    #tmp t1
    JOIN #tmp t2
        ON t2.OrderID <= t1.OrderID
GROUP BY
     t1.OrderID
    ,t1.ID
    ,t1.SomeDate
    ,t1.SomeValue
ORDER BY
    t1.OrderID

DROP TABLE #tmp

हां, मुझे लगता है कि यह सैम सैफ्रन के जवाब में 'टेस्ट 3' के बराबर है।
कोडुलिक

2

निम्नलिखित आवश्यक परिणाम देगा।

SELECT a.SomeDate,
       a.SomeValue,
       SUM(b.SomeValue) AS RunningTotal
FROM TestTable a
CROSS JOIN TestTable b
WHERE (b.SomeDate <= a.SomeDate) 
GROUP BY a.SomeDate,a.SomeValue
ORDER BY a.SomeDate,a.SomeValue

SomeDate पर क्लस्टर इंडेक्स होने से प्रदर्शन में सुधार होगा।


@ मुझे लगता है कि यह सवाल यह करने का एक कुशल तरीका खोजने की कोशिश कर रहा है, क्रॉस जॉइनिंग बड़े सेटों के लिए बहुत धीमी गति से होने जा रही है
सैम सैफ्रन

धन्यवाद, इसके वैकल्पिक उत्तर होने के लिए उपयोगी है, और कुशल समीक्षकों के लिए भी उपयोगी है
कोडुलिक

2

ज्वाइन का उपयोग करना Join में उपयोग करने के लिए एक और भिन्नता है। अब क्वेरी की तरह लग सकता है:

    SELECT a.id, a.value, SUM(b.Value)FROM   RunTotalTestData a,
    RunTotalTestData b
    WHERE b.id <= a.id
    GROUP BY a.id, a.value 
    ORDER BY a.id;

अधिक जानकारी के लिए आप इस लिंक http://askme.indianyouth.info/details/calculating-simple-running-totals-in-sql-server-12 पर देख सकते हैं


2

हालांकि इसका सबसे अच्छा तरीका यह है कि इसे एक विंडो फ़ंक्शन का उपयोग किया जाएगा, यह एक साधारण सहसंबद्ध उप-क्वेरी का उपयोग करके भी किया जा सकता है ।

Select id, someday, somevalue, (select sum(somevalue) 
                                from testtable as t2
                                where t2.id = t1.id
                                and t2.someday <= t1.someday) as runningtotal
from testtable as t1
order by id,someday;

0
BEGIN TRAN
CREATE TABLE #Table (_Id INT IDENTITY(1,1) ,id INT ,    somedate VARCHAR(100) , somevalue INT)


INSERT INTO #Table ( id  ,    somedate  , somevalue  )
SELECT 45 , '01/Jan/09', 3 UNION ALL
SELECT 23 , '08/Jan/09', 5 UNION ALL
SELECT 12 , '02/Feb/09', 0 UNION ALL
SELECT 77 , '14/Feb/09', 7 UNION ALL
SELECT 39 , '20/Feb/09', 34 UNION ALL
SELECT 33 , '02/Mar/09', 6 

;WITH CTE ( _Id, id  ,  _somedate  , _somevalue ,_totvalue ) AS
(

 SELECT _Id , id  ,    somedate  , somevalue ,somevalue
 FROM #Table WHERE _id = 1
 UNION ALL
 SELECT #Table._Id , #Table.id  , somedate  , somevalue , somevalue + _totvalue
 FROM #Table,CTE 
 WHERE #Table._id > 1 AND CTE._Id = ( #Table._id-1 )
)

SELECT * FROM CTE

ROLLBACK TRAN

आपको शायद कुछ जानकारी देनी चाहिए कि आप यहाँ क्या कर रहे हैं, और इस विशेष विधि के किसी भी फायदे / नुकसान पर ध्यान दें।
टीटी।

0

यहां कुल रनिंग गणना के 2 सरल तरीके दिए गए हैं:

दृष्टिकोण 1 : यह इस तरह लिखा जा सकता है यदि आपका DBMS एनालिटिकल फ़ंक्शंस का समर्थन करता है

SELECT     id
           ,somedate
           ,somevalue
           ,runningtotal = SUM(somevalue) OVER (ORDER BY somedate ASC)
FROM       TestTable

दृष्टिकोण 2 : यदि आप अपने डेटाबेस संस्करण / DBMS स्वयं विश्लेषणात्मक कार्यों का समर्थन नहीं करते हैं तो आप OPL APPLY का उपयोग कर सकते हैं

SELECT     T.id
           ,T.somedate
           ,T.somevalue
           ,runningtotal = OA.runningtotal
FROM       TestTable T
           OUTER APPLY (
                           SELECT   runningtotal = SUM(TI.somevalue)
                           FROM     TestTable TI
                           WHERE    TI.somedate <= S.somedate
                       ) OA;

नोट: - यदि आपको अलग-अलग विभाजनों के लिए चल रहे कुल की गणना अलग-अलग करनी है, तो इसे यहाँ पोस्ट किया जा सकता है: पंक्तियों में चल रहे कुल योगों की गणना करना और आईडी द्वारा समूहीकरण करना।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.