15

की गणना की गणना करता है मैं एक चलती औसत की गणना करने की कोशिश कर SQL Server 2008 R2 के साथ काम कर रहा हूं। मेरे विचार में प्रत्येक रिकॉर्ड के लिए, मैं 250 पिछले रिकॉर्ड के मान एकत्र करना चाहता हूं, और फिर इस चयन के लिए औसत की गणना करना चाहता हूं।टी-एसक्यूएल औसत

TransactionID | TimeStamp   | Value | MovAvg 
---------------------------------------------------- 
      1 | 01.09.2014 10:00:12 |  5 |  
      2 | 01.09.2014 10:05:34 |  3 | 
... 
      300 | 03.09.2014 09:00:23 |  4 | 

TransactionID अद्वितीय है:

मेरा विचार कॉलम इस प्रकार हैं। प्रत्येक TransactionID के लिए, मैं पिछले 250 रिकॉर्ड से अधिक कॉलम मान के लिए औसत की गणना करना चाहता हूं। तो ट्रांसएक्शनआईडी 300 के लिए, पिछले 250 पंक्तियों से सभी मान एकत्र करें (देखें लेनदेन आईडी द्वारा अवरुद्ध किया गया है) और फिर कॉलम मूवएवी में इन मानों के औसत का परिणाम लिखें। मैं रिकॉर्ड की एक श्रृंखला के भीतर डेटा एकत्र करने के लिए देख रहा हूँ।

+2

'भाग द्वारा' और 'ROW_NUMBER' – Mihai

+0

धन्यवाद। किसी भी मौके पर आपको यह सुझाव देना है कि इसे कैसे किया जाए? – RunW

+0

@RunW समान लेनदेन आईडी अलग-अलग मान के साथ दोहराता है, क्या लेनदेन आईडी के अलावा टाइमस्टैम्प कॉलम या पहचान कॉलम है? – radar

उत्तर

20

एसक्यूएल 2008 में खिड़की कार्यों बल्कि बाद के संस्करणों की तुलना में सीमित हैं और यदि मुझे याद है आप को सही केवल विभाजन और आप किसी भी पंक्तियों/रेंज फ्रेम सीमा का उपयोग नहीं कर सकते हैं कर सकते हैं लेकिन मुझे लगता है यह हो सकता है कि आप क्या चाहते:

;WITH cte (rn, transactionid, value) AS (
    SELECT 
     rn = ROW_NUMBER() OVER (ORDER BY transactionid), 
     transactionid, 
     value 
    FROM your_table 
) 

SELECT 
    transactionid, 
    value, 
    movagv = (
     SELECT AVG(value) 
     FROM cte AS inner_ref 
     -- average is calculated for 250 previous to current row inclusive 
     -- I might have set the limit one row to large, maybe it should be 249 
     WHERE inner_ref.rn BETWEEN outer_ref.rn-250 AND outer_ref.rn 
     ) 
FROM cte AS outer_ref 

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

SELECT 
    transactionid, 
    value, 
    -- avg over the 250 rows counting from the previous row 
    AVG(value) OVER (ORDER BY transactionid 
        ROWS BETWEEN 251 PRECEDING AND 1 PRECEDING), 
    -- or 250 rows counting from current 
    AVG(value) OVER (ORDER BY transactionid 
        ROWS BETWEEN 250 PRECEDING AND CURRENT ROW) 
FROM your_table 
+0

बहुत बहुत धन्यवाद। यह निश्चित रूप से ऐसा करने का तरीका है, लेकिन जैसा कि आप कहते हैं, प्रदर्शन काफी खराब है। आपकी सहायता की सराहना। – RunW

+0

क्या SQL 2008 में ऐसा करने का एक और अधिक प्रभावी तरीका है जो हर पंक्ति पर एक सहसंबंधित उप-क्वेरी नहीं चलाता है? मैं अपने मस्तिष्क को एक ऐसे समाधान के साथ कोशिश करने के लिए रैक कर रहा हूं जो मेरे निष्पादन समय को छोड़ देता है लेकिन मैं छोटा हो रहा हूं। – mitchimus

+0

@ मिचिमस हो सकता है, लेकिन मुझे किसी के बारे में पता नहीं है - मैंने इसके बारे में बहुत कुछ नहीं सोचा है हालांकि बाद के सर्वर संस्करणों के साथ बेहतर विकल्प हैं। – jpw

5

उपयोग एक Common Table Expression (CTE) प्रत्येक लेन-देन के लिए ROWNUM, तो शामिल करें ताकि पंक्ति संख्या पर अपने ख़िलाफ़ CTE शामिल होने के लिए:

बाद के संस्करणों आप विंडो फ्रेम कार्यों के लिए इस्तेमाल किया जा सकता था और कुछ इस तरह से किया साथ

आप पिछले मानों को औसत की गणना करने के लिए प्राप्त कर सकते हैं।

CREATE TABLE MyTable (TransactionId INT, Value INT) 

;with Data as 
(
    SELECT TransactionId, 
     Value, 
     ROW_NUMBER() OVER (ORDER BY TransactionId ASC) as rownum 
    FROM MyTable 
) 
SELECT d.TransactionId , Avg(h.Value) as MovingAverage 
FROM Data d 
JOIN Data h on h.rownum between d.rownum-250 and d.rownum-1 
GROUP BY d.TransactionId