2014-10-28 23 views
15

Hareketli bir ortalamayı hesaplamaya çalışırken SQL Server 2008 R2 ile çalışıyorum. Görüşümdeki her kayıt için, önceki 250 kayıtların değerlerini toplamak ve daha sonra bu seçim için ortalamayı hesaplamak istiyorum.T-SQL, hareketli ortalama hesaplanıyor

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 benzersizdir şu şekildedir:

Bence sütunlar bulunmaktadır. Her bir TransactionID için, önceki 250 kayıt üzerindeki sütun değeri için ortalama hesaplamak istiyorum. Yani TransactionID 300 için, önceki 250 satırdaki tüm değerleri topla (Görünüm TransactionID tarafından azalan şekilde sıralanır) ve daha sonra MovAvg sütununda bu değerlerin ortalamasının sonucunu yaz. Bir dizi kayıtta veri toplamaya çalışıyorum.

+2

"PARTITION BY" ve "ROW_NUMBER" öğesine bakın – Mihai

+0

Teşekkürler. Nasıl yapılacağına dair bir fikrin var mı? – RunW

+0

@RunW aynı işlem kimliğini farklı değerlerle tekrarlıyor, işlem kimliği dışında zaman damgası sütunu veya kimlik sütunu var mı? – radar

cevap

20

SQL 2008'deki pencere işlevleri sonraki sürümlere göre oldukça sınırlıdır ve doğru hatırlamıyorsam yalnızca bölümleme yapabilir ve herhangi bir satır/aralık çerçeve sınırını kullanamazsınız ancak bence bu sizin istediğiniz gibi olabilir:

;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 

Her satıra ilişkili bir alt sorgu uyguladığını ve performansın mükemmel olmayabileceğini unutmayın. Daha sonra, her bir işlem için rownum dahil böylece satır numarasına kendine karşı CTE katılmaya

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

Çok teşekkür ederim. Kesinlikle bunu yapmanın yolu, ama dediğin gibi, performans oldukça kötü. Yardımınıza minnettar olurum. – RunW

+0

SQL 2008'de bunu her satırda ilişkili bir alt sorgu çalıştırmayan daha verimli bir yolu var mı? Beynimi koruyarak infaz zamanımı düşüren bir çözüm bulmaya çalıştım ama kısa zamanda geliyorum. – mitchimus

+0

@mitchimus Belki olabilir, ancak hiç farkında değilim - daha sonra sunucu sürümleriyle daha iyi seçenekler olduğu için bunun hakkında pek düşünmedim. – jpw

5

kullanın Common Table Expression (CTE): Eğer pencere çerçevesi işlevlerini kullanılan ve böyle bir şey yapmış olabilir sonraki sürümleri ile

ile ortalamayı hesaplamak için önceki değerleri alabilirsiniz.