2009-07-20 9 views
24

मैं सभी कर्सर सेटअप और ब्रेवटी के लिए अस्थायी तालिका से चयन छोड़ रहा हूं। असल में, यह कोड प्रति लेनदेन के सभी लेनदेन के लिए एक चलती शेष राशि की गणना करता है।मैं कर्सर का उपयोग किए बिना SQL में चल रहे कुल की गणना कैसे करूं?

WHILE @@fetch_status = 0 
BEGIN 

    set @balance = @[email protected] 

    insert into @tblArTran values (--from artran table 
       @artranid, @trandate, @type, 
       @checkNumber, @refNumber,@custid, 
       @amount, @taxAmount, @balance, @postedflag, @modifieddate) 


    FETCH NEXT FROM artranCursor into 
      @artranid, @trandate, @type, @checkNumber, @refNumber, 
      @amount, @taxAmount,@postedFlag,@custid, @modifieddate 

END 

एक और प्रश्न का उत्तर इस कोड से प्रेरित होकर,

SELECT @nvcConcatenated = @nvcConcatenated + C.CompanyName + ', ' 
FROM tblCompany C 
WHERE C.CompanyID IN (1,2,3) 

मैं सोच रहा था अगर एसक्यूएल, उसी तरह यह तार concatonating है में संख्या योग करने के लिए अगर आप मेरी अर्थ मिल की क्षमता थी। यही है, एक कर्सर का उपयोग किए बिना प्रति पंक्ति "चलने वाली शेष राशि" बनाने के लिए।

क्या यह संभव है?

+1

इस दृश्य [http://stackoverflow.com/questions/1124317/query-for-total-should-keep-on-adding-with-each-row-of-cost-column से अलग पिछले रिकॉर्ड /1124682#1124682 ](http://stackoverflow.com/questions/1124317/query-for-total-should-keep-on-adding-with-each-row-of-cost-column/1124682#1124682) –

उत्तर

20

आप स्थानीय चर यहाँ समाधान करने के लिए अद्यतन पर एक नज़र लेने के लिए चाहते हो सकता है: http://geekswithblogs.net/Rhames/archive/2008/10/28/calculating-running-totals-in-sql-server-2005---the-optimal.aspx

DECLARE @SalesTbl TABLE (DayCount smallint, Sales money, RunningTotal money) 

DECLARE @RunningTotal money 

SET @RunningTotal = 0 

INSERT INTO @SalesTbl 
SELECT DayCount, Sales, null 
FROM Sales 
ORDER BY DayCount 

UPDATE @SalesTbl 
SET @RunningTotal = RunningTotal = @RunningTotal + Sales 
FROM @SalesTbl 

SELECT * FROM @SalesTbl 

अन्य सभी तरीकों से बेहतर साबित, लेकिन इसकी गारंटी पंक्ति आदेश के बारे में कुछ संदेह है। ठीक से काम करने के लिए जब अस्थायी तालिका हालांकि अनुक्रमित है ..

  • नेस्टेड उप क्वेरी 9300 एमएस लगता
  • स्व 6100 एमएस में शामिल होने
  • कर्सर 400 एमएस
  • अद्यतन स्थानीय चर के लिए 140 एमएस
+0

वाह, यह एक भयानक लेख है! मैं पोस्ट करने के लिए यह संभव था पता नहीं था। धन्यवाद । –

+2

हारून बर्ट्रेंड इस (http://stackoverflow.com/a/11313533/26167) जवाब में विभिन्न दृष्टिकोण, इस दृष्टिकोण के आसपास चेतावनियां की अधिक सहित का एक अच्छा सिंहावलोकन किया। – piers7

0

कि SELECT @nvcConcatonated बिट केवल एकल समेकित मूल्य लौटा रहा है। (हालांकि यह प्रति-पंक्ति के आधार पर मध्यवर्ती मानों की गणना कर रहा है, आप केवल अंतिम मान पुनर्प्राप्त करने में सक्षम हैं)।

तो, मुझे लगता है कि जवाब नहीं है। यदि आप एक अंतिम अंतिम मूल्य चाहते थे तो आप निश्चित रूप से SUM का उपयोग करेंगे।

मैं नहीं कह रहा हूं कि आप ऐसा नहीं कर सकते हैं, मैं बस इतना कह रहा हूं कि आप इस 'चाल' का उपयोग करके ऐसा नहीं कर सकते हैं।

10

एसक्यूएल कर्सर का उपयोग किए बिना योग चल रहा है बना सकते हैं, लेकिन यह कुछ मामलों में जहां एक कर्सर वास्तव में एक सेट के आधार पर समाधान की तुलना में अधिक performant है में से एक है (ऑपरेटरों दिया वर्तमान में एसक्यूएल सर्वर में उपलब्ध)। वैकल्पिक रूप से, एक सीएलआर समारोह कभी-कभी अच्छी तरह चमक सकता है। इटज़िक बेन-गण ने एसक्यूएल सर्वर मैगज़ीन में समेकित चलने पर एक उत्कृष्ट श्रृंखला की। श्रृंखला पिछले महीने समाप्त हुई, लेकिन यदि आपके पास ऑनलाइन सदस्यता है तो आप सभी लेखों तक पहुंच प्राप्त कर सकते हैं।

संपादित करें: यहां his latest article in the series (एसक्यूएल सीएलआर) है। यह देखते हुए कि आप एक महीने के लिए ऑनलाइन मासिक पास खरीदकर पूरी श्रृंखला तक पहुंच सकते हैं - 6 रुपये से कम - यदि आप सभी कोणों से समस्या को देखने में रुचि रखते हैं तो यह आपके लायक है। इट्ज़िक एक माइक्रोसॉफ्ट एमवीपी और बहुत उज्ज्वल टीएसक्यूएल कोडर है।

+1

धन्यवाद। कैसे बहुत निराशाजनक :( –

+1

थोड़ा प्रश्न के स्पर्श से दूर है, लेकिन जोड़ने के लिए कुछ उत्कृष्ट ठोस गुणवत्ता मेंटर्स, जो Itzik बेन-गण स्थापना से उपलब्ध पुस्तकों देखते हैं कि। वे से दूर दूर तक कर रहे हैं, सबसे अच्छा किताबें मैं पर खरीदा है SQL सर्वर, जो जानकारी मुझे कहीं और नहीं मिली है। Http://www.solidq.com/na/OurBooks.aspx – AdaTheDev

+0

मैंने इस उत्तर को अन-चेक किया क्योंकि हमें अभी भी इस प्रश्न के बहुत अच्छे उत्तर मिल रहे हैं और मैंने नहीं किया 'टी हतोत्साहित करने के लिए है कि आप एसक्यूएल सर्वर 2012 तक पहुंच है –

8

Oracle में और PostgreSQL 8.4 आप विंडो कार्यों का उपयोग कर सकते हैं:

SELECT SUM(value) OVER (ORDER BY id) 
FROM mytable 

MySQL में, आप एक ही उद्देश्य के लिए एक सत्र चर का उपयोग कर सकते हैं:

SELECT @sum := @sum + value 
FROM (
     SELECT @sum := 0 
     ) vars, mytable 
ORDER BY 
     id 

SQL Server में, यह एक दुर्लभ उदाहरण है एक कार्य जिसके लिए एक कर्सर एक पसंदीदा समाधान है।

+5

है, तो आप एक ही विंडो समारोह चल कुल गणना करने के लिए उपयोग कर सकते हैं चाहता हूँ। –

1

आप एक मौजूदा संख्या कर सकते हैं, यहाँ एक उदाहरण है, यह ध्यान रखें कि यह वास्तव में है कि तेजी से, क्योंकि यह, हर पंक्ति के लिए तालिका स्कैन करने के लिए करता है, तो अपनी मेज बड़ी है है नहीं है यह काफी समय लग सकता है और महंगा

create table #Test (id int, Value decimal(16,4)) 
insert #Test values(1,100) 
insert #Test values(2,100) 
insert #Test values(3,100) 
insert #Test values(4,200) 
insert #Test values(5,200) 
insert #Test values(6,200) 
insert #Test values(7,200) 

select *,(select sum(Value) from #Test t2 where t2.id <=t1.id) as SumValues 
from #test t1 

id Value  SumValues 
1 100.0000 100.0000 
2 100.0000 200.0000 
3 100.0000 300.0000 
4 200.0000 500.0000 
5 200.0000 700.0000 
6 200.0000 900.0000 
7 200.0000 1100.0000 
2

आप केवल चयनित खंड में एक सहसंबंधित सबक्वायरी शामिल कर सकते हैं।(यह बहुत बड़ी परिणाम सेट के लिए खराब प्रदर्शन होगा), लेकिन

Select <other stuff>, 
     (Select Sum(ColumnVal) From Table 
     Where OrderColumn <= T.OrderColumn) As RunningTotal 
    From Table T 
    Order By OrderColumn 
1

SQLTeam पर वहाँ चल रहे योग की गणना के बारे में भी एक article है। 3 तरीके की तुलना नहीं है यह करने के लिए, कुछ प्रदर्शन को मापने के साथ: एक subselect का उपयोग कर (के रूप में SQLMenace पद के अनुसार)

  • एक क्रॉस शामिल हों
  • का उपयोग कर

    • कर्सर का उपयोग कर
    • कर्सर अन्य समाधानों से बेहतर प्रदर्शन करते हैं, लेकिन यदि आपको कर्सर का उपयोग नहीं करना चाहिए, तो कम से कम एक विकल्प है।

    4

    प्रत्येक रिकॉर्ड के लिए एक रनिंग कुल की गणना करने का एक उदाहरण, लेकिन केवल तभी रिकॉर्ड के लिए ऑर्डरडेट उसी तारीख पर है। एक बार जब OrderDate एक अलग दिन के लिए है, तो एक नया चल रहा है कुल शुरू कर दिया और नए दिन के लिए जमा किया जाएगा: (तालिका संरचना और डेटा मान)

    select O.OrderId, 
    convert(char(10),O.OrderDate,101) as 'Order Date', 
    O.OrderAmt, 
    (select sum(OrderAmt) from Orders 
             where OrderID <= O.OrderID and 
              convert(char(10),OrderDate,101) 
             = convert(char(10),O.OrderDate,101)) 
               'Running Total' 
    from Orders O 
    order by OrderID 
    

    यहाँ परिणाम नमूना आदेश का उपयोग कर क्वेरी से लौट आए हैं तालिका:

    OrderId  Order Date OrderAmt Running Total        
    ----------- ---------- ---------- --------------- 
    1   10/11/2003 10.50  10.50 
    2   10/11/2003 11.50  22.00 
    3   10/11/2003 1.25  23.25 
    4   10/12/2003 100.57  100.57 
    5   10/12/2003 19.99  120.56 
    6   10/13/2003 47.14  47.14 
    7   10/13/2003 10.08  57.22 
    8   10/13/2003 7.50  64.72 
    9   10/13/2003 9.50  74.22 
    

    ध्यान दें कि "चल रहा कुल" 10.50 के एक मूल्य के साथ बाहर शुरू होता है, और उसके बाद 22.00 हो जाता है, और अंत में OrderID 3 के लिए 23.25 हो जाता है, के बाद से इन सभी रिकॉर्ड एक ही OrderDate है (10/11/2003)। लेकिन जब ऑर्डरआईडी 4 प्रदर्शित होता है तो रनिंग कुल रीसेट हो जाता है, और रनिंग कुल फिर से शुरू होता है। ऐसा इसलिए है क्योंकि ऑर्डरआईडी 4 की ऑर्डरडेट के लिए एक अलग तारीख है, फिर ऑर्डर आईडी 1, 2, और 3. प्रत्येक अद्वितीय तिथि के लिए इस रनिंग कुल की गणना एक सहसंबंधित उप क्वेरी का उपयोग करके एक बार फिर से पूरा की जाती है, हालांकि एक अतिरिक्त WHERE स्थिति आवश्यक है, जो पहचान की है कि विभिन्न रिकॉर्ड पर ऑर्डरडेट का दिन उसी दिन होना चाहिए। ऑर्डरडेट को एमएम/डीडी/वाई वाई वाई वाई प्रारूप में कन्वर्ट करने के लिए कन्वर्ट फ़ंक्शन का उपयोग करके यह कहां पूरा किया जाता है।

    0

    ध्यान दें कि निम्न में ऐसा करने के लिए एक चर का उपयोग करना एक मल्टीप्रोसेसर सिस्टम में विफल हो सकता है क्योंकि अलग-अलग पंक्तियों को विभिन्न प्रोसेसर पर गणना की जा सकती है और उसी प्रारंभिक मान का उपयोग कर समाप्त हो सकती है। मेरी समझ यह है कि एक थ्रेड का उपयोग करने के लिए इसे मजबूर करने के लिए एक प्रश्न संकेत का उपयोग किया जा सकता है, लेकिन मेरे पास यह जानकारी आसान नहीं है।

    अद्यतन @SalesTbl सेट @RunningTotal = RunningTotal = @RunningTotal + बिक्री @SalesTbl

    अन्य विकल्पों में से एक (एक कर्सर, एक खिड़की समारोह, या नेस्टेड क्वेरी) का उपयोग करने से आम तौर पर होने जा रहा है आपके विश्वसनीय परिणामों के लिए सबसे सुरक्षित शर्त।

    3

    एसक्यूएल सर्वर 2012 में और ऊपर तुम सिर्फ मूल तालिका के खिलाफ सीधे Sum विंडोइंग फ़ंक्शन का उपयोग कर सकते हैं:

    SELECT 
        artranid, 
        trandate, 
        type, 
        checkNumber, 
        refNumber, 
        custid, 
        amount, 
        taxAmount, 
        Balance = Sum(amount) OVER (ORDER BY trandate ROWS UNBOUNDED PRECEDING), 
        postedflag, 
        modifieddate 
    FROM 
        dbo.Sales 
    ; 
    

    यह बहुत अच्छी तरह से सभी समाधान की तुलना में प्रदर्शन करेंगे और के रूप में पाया त्रुटियों के लिए संभावित नहीं होगा "quirky अद्यतन" में।

    ध्यान दें कि आप ROWS संस्करण जब संभव का उपयोग करना चाहिए; RANGE संस्करण कम अच्छी तरह से प्रदर्शन कर सकता है।

    +0

    यह बहुत बढ़िया धन्यवाद है –

    0

    चयन TransactionDate, राशि, राशि + (योग x.amount से लेन-देन एक्स जहां x.TransactionDate < लेन-देन) Runningtotal लेनदेन

    जहां x.TransactionDate से < लेनदेन किसी भी हालत है कि सभी का प्रतिनिधित्व करेंगी हो सकता है वर्तमान एक

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

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