2015-10-08 11 views
5

बुरा विषय के लिए क्षमा करें, लेकिन मुझे यकीन है कि क्या यह कॉल करने के लिए नहीं था ..T-SQL में योग चल रहा है

मैं एक मेज यह की तरह लग रही है:

+-----++-----+ 
| Id ||Count| 
+-----++-----+ 
| 1 || 1 | 
+-----++-----+ 
| 2 || 5 | 
+-----++-----+ 
| 3 || 8 | 
+-----++-----+ 
| 4 || 3 | 
+-----++-----+ 
| 5 || 6 | 
+-----++-----+ 
| 6 || 8 | 
+-----++-----+ 
| 7 || 3 | 
+-----++-----+ 
| 8 || 1 | 
+-----++-----+ 

मैं बनाने के लिए कोशिश कर रहा हूँ इस तालिका से एक चयन जहां हर बार पंक्ति 1 + पंक्ति 2 + पंक्ति 3 (आदि) का एसयूएम 10 तक पहुंचता है, तो यह एक "एचआईटी" होता है, और गिनती फिर से शुरू होती है।

अनुरोध किया उत्पादन:

+-----++-----++-----+ 
| Id ||Count|| HIT | 
+-----++-----++-----+ 
| 1 || 1 || N | Count = 1 
+-----++-----++-----+ 
| 2 || 5 || N | Count = 6 
+-----++-----++-----+ 
| 3 || 8 || Y | Count = 14 (over 10) 
+-----++-----++-----+ 
| 4 || 3 || N | Count = 3 
+-----++-----++-----+ 
| 5 || 6 || N | Count = 9 
+-----++-----++-----+ 
| 6 || 8 || Y | Count = 17 (over 10..) 
+-----++-----++-----+ 
| 7 || 3 || N | Count = 3 
+-----++-----++-----+ 
| 8 || 1 || N | Count = 4 
+-----++-----++-----+ 

मैं यह करने के लिए कैसे करते हैं, और सबसे अच्छा प्रदर्शन के साथ? मुझे पता नहीं है ..

+0

[यहां देखें] (http://stackoverflow.com/a/31497897/3094533) के साथ टैग की गई प्रत्येक पंक्ति की आवश्यकता नहीं है। –

+0

dense_rank() का उपयोग करने के बारे में दिलचस्प विचार। शायद यह काम करेगा। अन्यथा मुझे एक कर्सर के साथ एक संग्रहित proc से डर है शायद इसकी आवश्यकता है। –

+0

यदि 'dense_rank()' चाल नहीं करता है, तो आप इसे एक पुनरावर्ती दृश्य के साथ भी कर सकते हैं। मेरा मानना ​​है कि 'dense_rank()' मार्ग बेहतर अनुकूलित किया जाएगा हालांकि। – JNevill

उत्तर

3

आप का उपयोग Recursive Queries

कृपया ध्यान दें निम्न क्वेरी आईडी मान संभालने सकता है, सभी अनुक्रम में हैं अन्यथा, ROW_NUMBER() का इस्तेमाल करें एक नया आईडी

WITH cte AS (
    SELECT id, [Count], [Count] AS total_count 
    FROM Table1 
    WHERE id = 1 
    UNION ALL 
    SELECT t2.id,t2.[Count], CASE WHEN t1.total_count >= 10 THEN t2.[Count] ELSE t1.total_count + t2.[Count] END 
    FROM Table1 t2 
    INNER JOIN cte t1 
    ON t2.id = t1.id + 1 
) 
SELECT * 
FROM cte 
ORDER BY id 

SQL Fiddle बनाने के लिए

1

मैं सच में आशा करती हूं कि अगर यह सीधी-सपाट खिड़की कार्यों का उपयोग कर यह करने के लिए संभव है किसी को हमें दिखा सकते हैं। यह असली चुनौती है।

इस बीच, यहां मैं रिकर्सन का उपयोग करके इसे कैसे करूँगा। यह अनुक्रम में अंतर को संभालता है, और पहले पंक्ति के किनारे के मामले को पहले से ही >= 10 पर संभालता है।

मैं भी डिफ़ॉल्ट प्रत्यावर्तन सीमा को निकालना maxrecursion संकेत गयी। लेकिन मैं ईमानदारी से नहीं जानता कि यह बड़ी मात्रा में डेटा के साथ कितनी अच्छी तरह से चलेंगे।

with NumberedRows as (
    select Id, Cnt, 
     row_number() over(order by id) as rn 
    from CountTable 
), RecursiveCTE as (
    select Id, Cnt, rn, 
     case when Cnt >= 10 then 0 else Cnt end as CumulativeSum, 
     case when Cnt >= 10 then 'Y' else 'N' end as hit 
    from NumberedRows 
    where rn = 1 
    union all 
    select n.Id, n.Cnt, n.rn, 
     case when (n.Cnt + r.CumulativeSum) >= 10 then 0 else n.Cnt + r.CumulativeSum end as CumulativeSum, 
     case when (n.Cnt + r.CumulativeSum) >= 10 then 'Y' else 'N' end as hit 
    from RecursiveCTE r 
    join NumberedRows n 
     on n.rn = r.rn + 1 
) 
select Id, Cnt, hit 
from RecursiveCTE 
order by Id 
option (maxrecursion 0) 

SQLFiddle Demo

4

यह एक टिप्पणी के लिए बहुत लंबा है।

आप क्योंकि breakpoints अग्रिम में नहीं जाना जाता है खिड़की/विश्लेषणात्मक कार्यों का उपयोग कर ऐसा नहीं कर सकते। कभी-कभी, ब्रेकपॉइंट्स की गणना करना संभव है। हालांकि, इस मामले में, ब्रेकपॉइंट पिछले मानों के एक गैर-रैखिक कार्य पर निर्भर करता है (मैं अभी "गैर-रैखिक" से बेहतर शब्द नहीं सोच सकता)। यही है, कभी-कभी पहले पंक्ति में "1" जोड़ना वर्तमान पंक्ति की गणना पर शून्य प्रभाव डालता है। कभी-कभी इसका बड़ा प्रभाव पड़ता है। निहितार्थ यह है कि गणना शुरुआत में शुरू होती है और डेटा के माध्यम से पुनरावृत्ति होती है।

समस्या के लिए मामूली संशोधन ऐसे कार्यों का उपयोग करके हल करने योग्य होगा। यदि समस्या, बजाय, प्रत्येक समूह के लिए अतिरिक्त राशि (योग को पुनरारंभ करने के बजाय) को ले जाने के लिए, समस्या संचयी रकम (और कुछ अन्य चालबाजी) का उपयोग करके हल करने योग्य होगी।

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

1

कैसे इस का उपयोग करते हुए चल रहा है योग के बारे में:

DECLARE @Data TABLE(
    Id INT 
    ,SubTotal INT 
) 


INSERT INTO @Data 
    VALUES(1, 5) 

INSERT INTO @Data 
    VALUES(2, 3) 

INSERT INTO @Data 
    VALUES(3, 4) 

INSERT INTO @Data 
    VALUES(4, 4) 

INSERT INTO @Data 
    VALUES(5, 7) 

DECLARE @RunningTotal INT = 0 
DECLARE @HitCount INT = 0  

SELECT 
     @RunningTotal = CASE WHEN @RunningTotal < 10 THEN @RunningTotal + SubTotal ELSE SubTotal END 
     ,@HitCount = @HitCount + CASE WHEN @RunningTotal >= 10 THEN 1 ELSE 0 END 
     FROM @Data ORDER BY Id 

SELECT @HitCount -- Outputs 2 

करने के बाद सवाल मैं देख रहा हूँ इस के लिए आवश्यक उत्पादन को पूरा नहीं करता फिर से पढ़ें - मैं जवाब छोड़ देंगे के रूप में यह देखने वाले व्यक्ति के कुछ काम का हो सकता है इस प्रकार की समस्या के चल रहे कुल समाधान के उदाहरण के लिए, जिसे वाई या एन

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