2015-12-22 9 views
11

मैं एक मेज है कि इस तरह दिखता है:एसक्यूएल सर्वर: सशर्त कुल;

Year  Value 
    ----------------- 
    2013  -0.0016 
    2014  -0.0001 
    2015  0.0025 
    2016  -0.0003 
    2017  0.0023 
    2018  0.0002 

और मैं एक सशर्त कुल कि एक नया स्तंभ में परिणाम प्रदर्शन करने की जरूरत है। निम्नानुसार स्थितियां हैं:

यदि मान ऋणात्मक है तो एकत्रीकरण शुरू होता है और मूल्य सकारात्मक होने तक नहीं रुकता है। तो फिर कुछ भी नहीं जब तक मूल्य फिर से नकारात्मक है ... परिणाम इस तरह दिखेगा:

Year  Value  AggCol 
    2013  -0.0016  -0.0016 
    2014  -0.0001  -0.0017 
    2015  0.0025  0.0008 
    2016  -0.0003  -0.0003 
    2017  0.0023  0.002 
    2018  0.0002  0.0002 

यह यूडीएफ के रूप में करीब है के रूप में मैं मिल गया है:

create function dbo.fn(@cYear numeric, @rate float) 
returns float 
as 
begin 
    declare @pYear numeric 
    declare @return float 

    set @pYear = @cYear - 1 

    set @return = (select 
         case 
          when Value < 0 and @rate > 0 then null 
          when Value < 0 then Value + @rate 
          else @rate 
         end 
        from Table1 
        where [year] = @pYear) 

    return @return 
end 

मैं सी # में एक जवाब के साथ ठीक हूँ अगर यह आसान होगा लेकिन एसक्यूएल पसंद करेंगे। मेरे द्वारा किए गए फ़ंक्शन के साथ समस्या यह है कि मुझे मूल्य को सकारात्मक होने पर मूल्य में जोड़ने के लिए पिछली पंक्ति से परिणामों को पकड़ने में सक्षम होना चाहिए।

मैं यहाँ सुराग और कोई खुशी के लिए खोज पर सारी रात ...

संपादित था: तो भाकपा मूल्यों के रूप में इन के बारे में सोच के लिए साल आपके वाहक द्वारा अपने सेलफोन बिल को लागू किया जा करने के लिए ... वे केवल सीपीआई द्वारा आपके बिल को बढ़ाने जा रहे हैं, और इसे कभी कम नहीं करते हैं (यदि सीपीआई नकारात्मक है) ... लेकिन चालू वर्ष सीपीआई सकारात्मक होने पर वे पिछले वर्षों के नकारात्मक सीपीआई को ऑफसेट करेंगे (या योग परिणाम एक सकारात्मक में) ...

जो मदद कर सकता है या नहीं भी हो सकता है लेकिन यह स्थिति है।

+0

SQL सर्वर का कौन सा संस्करण आप उपयोग कर रहे हैं? –

+0

आप SQL सर्वर में किसी क्वेरी का उपयोग करके ऐसा कर सकते हैं, लेकिन इसके लिए रिकर्सिव सीटीई की आवश्यकता है। –

+0

2012 और मैं सीटीई के साथ ठीक हूं ... डीबीओ एक्सेस है, इसलिए कुछ भी आवश्यक कर सकते हैं। – user3486773

उत्तर

6
DECLARE @t TABLE ([Year] INT, Value MONEY) 

INSERT INTO @t 
VALUES (2013, -0.0016), 
     (2014, -0.0001), 
     (2015, 0.0025), 
     (2016, -0.0003), 
     (2017, 0.0023), 
     (2018, 0.0002) 

SELECT t1.Year , 
     t1.Value , 
     oa.AggCol 
FROM @t t1 
     OUTER APPLY (SELECT SUM(Value) AS AggCol 
         FROM  @t t2 
         WHERE  Year <= t1.Year 
           AND Year > (SELECT ISNULL(MAX(Year), 0) 
              FROM @t 
              WHERE Year < t1.Year AND Value > 0) 
        ) oa 

आउटपुट:

Year Value AggCol 
2013 -0.0016 -0.0016 
2014 -0.0001 -0.0017 
2015 0.0025 0.0008 
2016 -0.0003 -0.0003 
2017 0.0023 0.002 
2018 0.0002 0.0002 

इसका मतलब है कि: प्रत्येक पंक्ति के लिए मुझे मूल्यों वर्तमान पंक्ति से कम या बराबर और सकारात्मक मूल्य है कि वर्तमान पंक्ति से पहले दिखाई देता है, या शुरुआती के साथ अधिक से अधिक पंक्ति से अधिक की राशि देना 0 से अगर ऐसा कोई नहीं मिला।

+0

आप महोदय प्रकृति का एक सनकी हैं! मेरा मतलब है कि सबसे प्रशंसनीय तरीके से संभव है क्योंकि मुझे गति से उड़ा दिया गया है, आपने इसका जवाब दिया! आपका बहुत बहुत धन्यवाद!!!! – user3486773

+0

@ user3486773, दिलचस्प प्रश्न के लिए भी आपको धन्यवाद। –

+0

यह एक शानदार प्रयास है और प्रदान किए गए परीक्षण डेटा के साथ काम करता है लेकिन यह चलने वाले योग को सकारात्मक संख्या बनाने के लिए कई सकारात्मक मान लेते समय टूट जाता है। जैसे 2014 से .0001 और वर्ष 2015 में बदलें गलत मूल्य मौजूद होगा। – Matt

0

आप भी इसे खिड़की फ़ंक्शन का उपयोग कर सकते हैं:

;WITH PrevValues AS (
    SELECT Year, Value, 
      LAG(Value) OVER (ORDER BY Year) AS prevValue 
    FROM Table1 
), Flags AS (
    SELECT Year, Value, 
     CASE 
      WHEN Value < 0 AND prevValue > 0 THEN 2 -- next slice 
      WHEN Value < 0 OR prevValue < 0 THEN 1 -- same slice 
      WHEN Value > 0 AND prevValue > 0 THEN -1 -- not in a slice 
     END AS flag 
    FROM PrevValues 
), Islands AS (
    SELECT Year, Value,  
     CASE 
      WHEN flag = -1 THEN -1 
      ELSE SUM(flag) OVER (ORDER BY Year)  
       - 
       ROW_NUMBER() OVER (ORDER BY Year) 
     END AS grp 
    FROM Flags 
) 
SELECT Year, Value, 
     CASE 
      WHEN grp = -1 THEN Value 
      ELSE SUM(Value) OVER (PARTITION BY grp ORDER BY Year) 
     END AS AggCol 
FROM Islands 
ORDER BY Year 

विचार पंक्तियों जिस पर चल रहे योग लागू किया जाता है के द्वीपों की पहचान है।

Demo here

+0

यह एक अच्छा प्रयास है और प्रदान किए गए परीक्षण डेटा के साथ काम करता है लेकिन यह चल रहा है जब यह एक सकारात्मक संख्या को सकारात्मक संख्या बनाने के लिए कई सकारात्मक मान लेगा। जैसे 2014 से .0001 और वर्ष 2015 में बदलें गलत मूल्य मौजूद होगा। – Matt

0
DECLARE @t TABLE ([Year] INT, Value MONEY) 
INSERT INTO @t 
VALUES (2013,-0.0016),(2014,0.0001),(2015,0.0025),(2016,-0.0003),(2017,0.0023),(2018,0.0002) 

;WITH cteRowNum AS (
    SELECT *, ROW_NUMBER() OVER (ORDER BY Year) as RowNum 
    FROM 
     @t 
) 
, cteRecursive AS (
    SELECT 
     Year 
     ,Value 
     ,Value as AggCol 
     ,RowNum 
    FROM 
     cteRowNum 
    WHERe 
     RowNum = 1 

    UNION ALL 

    SELECT 
     c.Year 
     ,c.Value 
     ,CASE 
      WHEN AggCol >= 0 THEN c.Value 
      ELSE AggCol + c.Value 
     END 
     ,c.RowNum 
    FROM 
     cteRecursive r 
     INNER JOIN cteRowNum c 
     ON r.RowNum + 1 = c.RowNum 
) 

SELECT Year, Value, AggCol 
FROM 
    cteRecursive 

नोट ये अलग डेटा सेट को आप क्या प्रदान की तुलना में! यहाँ के परिणाम हैं

Year Value  AggCol 
2013 -0.0016  -0.0016 
2014  0.0001  -0.0015 
2015  0.0025  0.001 
2016 -0.0003  -0.0003 
2017  0.0023  0.002 
2018  0.0002  0.0002 

अपने मूल परीक्षण डाटा के साथ समस्या यह है कि यह स्थिति है जहाँ इसे चलाने योग सकारात्मक बनाने के लिए कई अनुक्रमिक सकारात्मक रिकॉर्ड ले जाएगा के लिए खाते नहीं किया है। इसके बाद, जब मैं अपना उत्तर पोस्ट कर रहा हूं, तो दोनों अन्य उत्तर गलत हैं। तो मैंने केवल 2014 के रिकॉर्ड को सकारात्मक में बदल दिया .0001 और आप देख सकते हैं कि यह समाधान कैसे काम करता है और अन्य नहीं करते हैं।

शायद खिड़की कार्यों के साथ ऐसा करने के तरीके हैं लेकिन पुनरावर्ती CTE सुंदर सीधे आगे तो है मुझे लगता है कि मार्ग चला गया:

  • पहले डाटासेट पर एक ROW_NUMBER निर्माण स्थिति के लिए खाते में शामिल में उपयोग करने के लिए यदि आपके डेटासेट या किसी चीज़ में कोई वर्ष गुम है।
  • अगला पंक्ति संख्या का उपयोग करके एक बार रिकर्सिव सीटीई और चरण 1 पंक्ति का निर्माण करें और यह निर्धारित करें कि कुल मूल्य को रीसेट या जोड़ा जाना चाहिए या नहीं, पिछली पंक्ति मान सकारात्मक या नकारात्मक है या नहीं।

यहाँ Giorgos & Giorgi के जवाब के परिणाम अगर आप परीक्षण डेटा का परिवर्तन करना हैं:

Year Value  AggCol 
2013 -0.0016  -0.0016 
2014  0.0001  -0.0015 
2015  0.0025  0.0025 
2016 -0.0003  -0.0003 
2017  0.0023  0.002 
2018  0.0002  0.0002 

आप साल के लिए AggCol के साथ समस्या यह देख सकते हैं 2015 गलत

है कृपया ध्यान दें मुझे लगता है कि उत्तर महान प्रयास हैं और अंतराल/द्वीपों की बात करते समय कुछ वास्तविक कौशल/कोड दिखाते हैं। मैं सिर्फ पोस्ट की गुणवत्ता को बढ़ाने पर हमला करने की कोशिश नहीं कर रहा हूं।

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