2009-06-16 15 views
7

मेरे पास SQL ​​सर्वर में एक तालिका है जो हार्डवेयर के एक टुकड़े के आंकड़े संग्रहीत करती है, तालिका में पंक्तियां किसी दिए गए दूसरे के लिए डेटा का प्रतिनिधित्व करती हैं। यह उदाहरण के लिए होता है, ये कॉलम:टी-एसक्यूएल समय औसत

timestamp (DateTime) 
value (int) 

क्या मैं किसी दिए गए दिनांक/समय सीमा के लिए मेज से डेटा का चयन लेकिन इस तरह से इसे वापस कर रहा है क्या करना चाहते हैं कि यह एक निश्चित समय अवधि के लिए औसत (जैसे कि 1 मिनट, 5 मिनट, 1 दिन इत्यादि) दी गई सीमा के बीच। तो एक घंटे के लिए मेरे पास 1 मिनट औसत की 60 पंक्तियां होंगी।

मैं इसके साथ कहां से शुरू करूं? कोई भी कोई अंक या विचार?

उत्तर

9

आप अपने टाइमस्टैम्प के डेटपर्ट पर एक चयन और समूह कर सकते हैं।

उदाहरण के लिए:

SELECT 
    DATEPART(hh, [timestamp]), 
    DATEPART(mi, [timestamp]), 
    AVG([value]) 
FROM 
    YourTable 
WHERE 
    [timestamp] BETWEEN '2009-01-01 00:00:00.000' AND '2009-02-01 00:00:00.000' 
GROUP BY 
    DATEPART(hh, [timestamp]), 
    DATEPART(mi, [timestamp]) 

संपादित करें: अपने और अधिक जटिल समय 5 मिनट की तरह फैला होता है के लिए, आप के रूप में निम्नानुसार DatePart पर एक विभाजन कर सकते हैं।

DATEPART(mi, [timestamp])/5 * 5 
+0

+1 अच्छा क्वेरी और आसान – Andomar

+0

को पढ़ने के लिए यह एक का इलाज धन्यवाद काम करता है! – Lloyd

5
WITH cal(m) AS 
     (
     SELECT 1 
     UNION ALL 
     SELECT m + 1 
     FROM cal 
     WHERE m < 60 
     ) 
SELECT DATEADD(minute, m, @start), AVG(value) 
FROM cal 
LEFT JOIN 
     timestamp 
ON  timestamp > DATEADD(minute, m, @start) 
     AND timestamp <= DATEADD(minute, m + 1, @start) 
GROUP BY 
     m 

इसमें दिए गए घंटे के अंदर सभी मिनट, यहां तक ​​कि उन जिसके लिए कोई रिकॉर्ड कर रहे हैं के लिए औसत का चयन करेंगे।

+0

+1। अच्छा है। ... –

+0

एक रिकर्सिव सीटीई के साथ एक संख्या तालिका का निर्माण, पहले नहीं देखा - मुझे यह पसंद है! सीटीई के लिए – AakashM

+0

+1! –

1

रॉबिन दिवस से पोस्ट करने के लिए इसके अलावा, आप की तरह 5 मिनट के अंतराल से समूह कर सकते हैं:

GROUP BY 
    DATEPART(hh, [timestamp]), 
    DATEPART(mi, [timestamp])/5 

और अगर आप डीवाई पर कई दिनों तक चलते हैं, समूह, वर्ष के दिन के लिए करना चाहते हैं:

GROUP BY 
    DATEPART(dy, [timestamp]), 
    DATEPART(hh, [timestamp]), 
    DATEPART(mi, [timestamp])/5 
1

आप इस डेटा आप एक अनुक्रमित दृश्य विचार करना चाह सकते के लिए एक उच्च पढ़ें/लिखें अनुपात करने जा रहे हैं। मैंने समय के बाल्टी से कुल मिलाकर इस दृष्टिकोण का उपयोग किया है।

create table timeSeries (
    timeSeriesId int identity primary key clustered 
    ,updateDate datetime not null 
    ,payload float not null 
) 

insert timeSeries values ('2009-06-16 12:00:00', rand()) 
insert timeSeries values ('2009-06-16 12:00:59', rand()) 
insert timeSeries values ('2009-06-16 12:01:00', rand()) 
insert timeSeries values ('2009-06-16 12:59:00', rand()) 
insert timeSeries values ('2009-06-16 01:00:00', rand()) 
insert timeSeries values ('2009-06-16 1:30:00', rand()) 
insert timeSeries values ('2009-06-16 23:59:00', rand()) 
insert timeSeries values ('2009-06-17 00:01:00', rand()) 
insert timeSeries values ('2009-06-17 00:01:30', rand()) 


create view timeSeriesByMinute_IV with schemabinding as 
select 
    dayBucket = datediff(day, 0, updateDate) 
    ,minuteBucket = datediff(minute, 0, (updateDate - datediff(day, 0, updateDate))) 
    ,payloadSum = sum(payLoad) 
    ,numRows = count_big(*) 
from dbo.timeSeries 
group by 
    datediff(day, 0, updateDate) 
    ,datediff(minute, 0, (updateDate - datediff(day, 0, updateDate))) 
go 

create unique clustered index CU_timeSeriesByMinute_IV on timeSeriesByMinute_IV (dayBucket, minuteBucket) 
go 


create view timeSeriesByMinute as 
select 
    dayBucket 
    ,minuteBucket 
    ,payloadSum 
    ,numRows 
    ,payloadAvg = payloadSum/numRows 
from dbo.timeSeriesByMinute_IV with (noexpand) 
go 

declare @timeLookup datetime, @dayBucket int, @minuteBucket int 
select 
    @timeLookup = '2009-06-16 12:00:00' 
    ,@dayBucket = datediff(day, 0, @timeLookup) 
    ,@minuteBucket = datediff(minute, 0, (@timeLookup - datediff(day, 0, @timeLookup))) 

select * from timeSeriesByMinute where dayBucket = @dayBucket and minuteBucket = @minuteBucket 

आप कोड ब्लॉक के अंत में उदाहरण देखने को देख सकते हैं: मैं बस blogging the example के लिए चारों ओर हो गया है, यहाँ कोड है। स्पष्ट रूप से आप केवल एक विशेष दिन की तलाश करने के बजाय सीमाओं को क्वेरी में परिभाषित कर सकते हैं बाल्टी/मिनट बाल्टी जोड़ी।

1

मैं Quassnoi के जवाब निम्न परिवर्तन के बिना काम करने के लिए नहीं मिल सका:

WITH cal(m) AS 
    (
    SELECT 1 
    UNION ALL 
    SELECT m + 1 
    FROM cal 
    WHERE m < 60 
    ) 
SELECT DATEADD(minute, m, @start) m, AVG(value) 
FROM cal 
LEFT JOIN 
    YourTable 
ON  timestamp > DATEADD(minute, m, @start) 
    AND timestamp <= DATEADD(minute, m + 1, @start) 
GROUP BY 
    m 
संबंधित मुद्दे