2009-05-26 15 views
7

मैं उसी चयन कथन में पिछली पंक्तियों के कॉलम के आधार पर SELECT कथन में एक औसत औसत कॉलम रखने का प्रयास कर रहा हूं। मुझे जिस औसत की आवश्यकता है वह परिणामस्वरूप पिछली पंक्तियों पर आधारित है।एसक्यूएल एक रनिंग औसत कॉलम की गणना के लिए स्टेटमेंट का चयन करें

मुझे

Id  Number  Average 
1    1   NULL 
2    3   NULL 
3    2   NULL 
4    4    2 <----- Average of (1, 3, 2),Numbers from previous 3 rows 
5    6    3 <----- Average of (3, 2, 4),Numbers from previous 3 rows 
.    .    . 
.    .    . 

औसत स्तंभ के पहले 3 पंक्तियों अशक्त क्योंकि वहाँ कोई पिछले पंक्तियों हैं समझाता हूँ। औसत कॉलम में पंक्ति 4 पिछले 3 पंक्तियों से संख्या कॉलम का औसत दिखाती है।

मुझे SQL चयन कथन बनाने की कोशिश करने में कुछ मदद चाहिए जो ऐसा करेगा।

+0

आप किस प्रकार का SQL डेटाबेस उपयोग कर रहे हैं? –

+0

मैं SQL Server 2008 का उपयोग कर रहा हूं। – HYP

+0

मुझे लगता है कि यह उन दुर्लभ मामलों में से एक है जहां कर्सर सबसे तेज़ होने जा रहे हैं ... केवल पिछले 3 पंक्तियों को वर्र्स में रखें ... –

उत्तर

11

यह करना चाहिए:

--Test Data 
CREATE TABLE RowsToAverage 
    (
    ID int NOT NULL, 
    Number int NOT NULL 
    ) 

INSERT RowsToAverage(ID, Number) 
SELECT 1, 1 
UNION ALL 
SELECT 2, 3 
UNION ALL 
SELECT 3, 2 
UNION ALL 
SELECT 4, 4 
UNION ALL 
SELECT 5, 6 
UNION ALL 
SELECT 6, 8 
UNION ALL 
SELECT 7, 10 

--The query 
;WITH NumberedRows 
AS 
(
SELECT rta.*, row_number() OVER (ORDER BY rta.ID ASC) AS RowNumber 
FROM RowsToAverage rta 
) 

SELECT nr.ID, nr.Number, 
     CASE 
      WHEN nr.RowNumber <=3 THEN NULL 
      ELSE ( SELECT avg(Number) 
        FROM NumberedRows 
        WHERE RowNumber < nr.RowNumber 
        AND  RowNumber >= nr.RowNumber - 3 
       ) 
     END AS MovingAverage 
FROM NumberedRows nr 
+0

+1, यह मेरे सिस्टम –

+0

+ 1 पर बहुत सही ढंग से चलता है। बहुत ही सुरुचिपूर्ण समाधान। एमवीपी, एमवीपी, एमवीपी! –

+0

बहुत ही सुरुचिपूर्ण समाधान। 9,000 पंक्तियों के साथ, मेरे देव सर्वर पर लगभग 45 सेकंड लगते हैं। इस तकनीक का अधिक कुशलतापूर्वक उपयोग करने का कोई तरीका है। –

0

कुछ समाधान देखें here। मुझे यकीन है कि आप उनमें से एक को आसानी से अनुकूलित कर सकते हैं।

+1

जबकि यह सैद्धांतिक रूप से सवाल का जवाब दे सकता है, [यह बेहतर होगा] (http://meta.stackexchange.com/q/8259) शामिल करने के लिए यहां उत्तर के आवश्यक भाग, और संदर्भ के लिए लिंक प्रदान करते हैं। – Sklivvz

1

संपादित करें: मैं कहना है कि यह तीन पिछले रिकॉर्ड औसत के बराबर होगा ...

एक सामान्य चल औसत के लिए याद किया, मुझे लगता है कि कुछ इस तरह काम करेगा :

SELECT 
    id, number, 
    SUM(number) OVER (ORDER BY ID)/
     ROW_NUMBER() OVER (ORDER BY ID) AS [RunningAverage] 
FROM myTable 
ORDER BY ID 
+0

@Aaron Alton's RowsToAverage तालिका का उपयोग करते समय (मैंने MyTable से ROWToAverage से बदल दिया), मुझे एक त्रुटि मिलती है: संदेश 102, स्तर 15, राज्य 1, रेखा 3 'ऑर्डर' के पास गलत वाक्यविन्यास। –

+0

आप किस आरडीबीएमएस का उपयोग कर रहे हैं? विंडिंग फ़ंक्शन केवल SQL 2005 और अधिक में उपलब्ध हैं। –

+0

मुझे यह जोड़ना चाहिए कि ओपी ने उल्लेख किया है कि वे SQL 2008 का उपयोग कर रहे हैं। –

0

आप इस सही मायने में performant होना चाहता हूँ, और SQL सर्वर की एक शायद ही कभी इस्तेमाल किया क्षेत्र में खुदाई करने के लिए डर arn't हैं, तो आप एक कस्टम योग समारोह लिख ध्यान देना चाहिए। एसक्यूएल सर्वर 2005 और 2008 ने तालिका में सीएलआर एकीकरण लाया, जिसमें उपयोगकर्ता कुल कार्यों को लिखने की क्षमता भी शामिल है। एक कस्टम रनिंग कुल कुल, इस तरह से चल रहे औसत की गणना करने का सबसे प्रभावी तरीका होगा।

8

यह मानते हुए कि ईद स्तंभ अनुक्रमिक है, यहाँ "MyTable" नामक एक मेज के लिए एक सरल प्रश्न है:

SELECT 
    b.Id, 
    b.Number, 
    (
     SELECT 
     AVG(a.Number) 
     FROM 
     MyTable a 
    WHERE 
     a.id >= (b.Id - 3) 
     AND a.id < b.Id 
     AND b.Id > 3 
    ) as Average 
FROM 
    MyTable b; 
+0

उहम्म। अनुक्रमिक आईडी मानते हैं, यह भी काम करता है। +1 –

+0

यह भी काम कर सकता है अगर तालिका में कोई पंक्तियां नहीं हटाई गईं। मैंने पंक्ति-संख्या() से अधिक (आरटीएआईआईडी एएससी द्वारा आदेश) के कारण हारून अल्टन के समाधान को स्वीकार किया है। – HYP

0

वैकल्पिक रूप से आप denormalize कर सकते हैं और दुकान चलाने मूल्यों precalculated। यहाँ वर्णित:

http://sqlblog.com/blogs/alexander_kuznetsov/archive/2009/01/23/denormalizing-to-enforce-business-rules-running-totals.aspx

चयन के प्रदर्शन के रूप में तेजी से के रूप में यह जाता है। बेशक, संशोधन धीमे हैं।

2

एक साधारण आत्म में शामिल होने के लिए बहुत एक पंक्ति की तुलना में बेहतर संदर्भित सबक्वेरी

उत्पन्न परीक्षण डेटा 10k पंक्तियों प्रदर्शन करने के लिए प्रतीत होता है:

drop table test10k 
create table test10k (Id int, Number int, constraint test10k_cpk primary key clustered (id)) 

;WITH digits AS (
    SELECT 0 as Number 
    UNION SELECT 1 
    UNION SELECT 2 
    UNION SELECT 3 
    UNION SELECT 4 
    UNION SELECT 5 
    UNION SELECT 6 
    UNION SELECT 7 
    UNION SELECT 8 
    UNION SELECT 9 
) 
,numbers as (
    SELECT 
     (thousands.Number * 1000) 
     + (hundreds.Number * 100) 
     + (tens.Number * 10) 
     + ones.Number AS Number 
    FROM digits AS ones 
    CROSS JOIN digits AS tens 
    CROSS JOIN digits AS hundreds 
    CROSS JOIN digits AS thousands 
) 
insert test10k (Id, Number) 
select Number, Number 
from numbers 

मैं से बाहर पहले 3 पंक्तियों के विशेष मामले खींच होगा मुख्य प्रश्न, यदि आप वाकई इसे पंक्ति सेट में चाहते हैं तो आप उन सभी को वापस कर सकते हैं। स्व में शामिल होने क्वेरी:

;WITH NumberedRows 
AS 
(
    SELECT rta.*, row_number() OVER (ORDER BY rta.ID ASC) AS RowNumber 
    FROM test10k rta 
) 

SELECT nr.ID, nr.Number, 
    avg(trailing.Number) as MovingAverage 
FROM NumberedRows nr 
    join NumberedRows as trailing on trailing.RowNumber between nr.RowNumber-3 and nr.RowNumber-1 
where nr.Number > 3 
group by nr.id, nr.Number 

मेरी मशीन पर इस बारे में 10 सेकंड लेता है, सबक्वेरी दृष्टिकोण है कि हारून एल्टन का प्रदर्शन लगभग 45 सेकंड लेता है (के बाद मैं अपने परीक्षण स्रोत तालिका प्रतिबिंबित करने के लिए इसे बदल):

;WITH NumberedRows 
AS 
(
    SELECT rta.*, row_number() OVER (ORDER BY rta.ID ASC) AS RowNumber 
    FROM test10k rta 
) 
SELECT nr.ID, nr.Number, 
    CASE 
      WHEN nr.RowNumber <=3 THEN NULL 
      ELSE ( SELECT avg(Number) 
          FROM NumberedRows 
          WHERE RowNumber < nr.RowNumber 
          AND    RowNumber >= nr.RowNumber - 3 
        ) 
    END AS MovingAverage 
FROM NumberedRows nr 

यदि आप एक सेट सांख्यिकी प्रोफ़ाइल करते हैं, तो आप देख सकते हैं कि स्वयं के शामिल होने से टेबल स्पूल पर 10k निष्पादन होते हैं। सबक्वायरी में फिल्टर, कुल, और अन्य चरणों पर 10k निष्पादन होते हैं।

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