2017-01-26 21 views
0

このクエリを使用して、値の時間平均を取得していますが、うまくいくようです。分の平均値を取得

select Time_Stamp_Hour = dateadd(hh,datepart(hh,Time_Stamp), cast(CAST(Time_Stamp as date) as datetime)) 
     ,AvgValue = AVG(Value) 
from ValueLog 
group by dateadd(hh,datepart(hh,Time_Stamp) 
     ,cast(CAST(Time_Stamp as date) as datetime)) 

1日の平均を分単位で取得する必要があるため、1日分の結果には1440個のレコードが必要です。

私はmiにhhを切り替えようとしましたが、毎日時間分解なしで1日全体の平均60個の分が得られます。この声明を日中の1時間ごとの分平均に変換するにはどうすればよいですか?私の代わりにHHと上記の文のマイルを使用しているとき(ちょうど00を示している)正しい時間を返さないのSQL Serverに2012

sample result when using mi instead of hh

時間の列を使用していると私は一日あたり60件の結果を得ます。

ここでは、結果が正しく表示される条件としてhhを使用して上記のステートメントを実行する例を示します。

hh

+0

「分平均」とはどういう意味ですか? – iamdave

+0

[MCVE]を追加することはできますか(http://meta.stackoverflow.com/questions/333952/why-should-i-provide-an-mcve-for-what-seems-to-me-to-be- a-very-simple-sql-query)をこの質問に追加しますか? –

+0

私はタイムスタンプとサンプル値の2つの列を持ち、数秒ごとに記録されるテーブルを持っています。上記のSELECT文を使用して、それらのサンプルの時間平均を取得することができます。私はこれをさらに進歩させ、分の平均を取る必要があります。 –

答えて

1

タイムスタンプ、使用から秒を切り捨てる:dateadd(minute, datediff(minute, 0, Time_Stamp), 0)

select Time_Stamp_Hour_Minute = dateadd(minute, datediff(minute, 0, Time_Stamp), 0) 
    , AvgValue = avg(Value) 
from ValueLog 
group by dateadd(minute, datediff(minute, 0, Time_Stamp), 0) 

またdateadd(hour, datediff(hour, 0, Time_Stamp), 0)に時間単位で切り捨てるためにあなたの質問に式を置き換えることができます。あなたがやろうとしているように聞こえる何をしている、hh:miとして時間を返しますconvert(varchar(5),time_stamp,8)を使用して


。スタイル8はフォーマットhh:mi:ssを返し、それをvarchar(5)に変換すると、最初の5文字(hh:mi)に制限されます。

select Time_Stamp_Hour_Minute = convert(varchar(5),Time_Stamp,8) 
     , AvgValue = avg(Value) 
from ValueLog 
group by convert(varchar(5),Time_Stamp,8) 

参照:cast() and convert() styles

+0

私はあなたが私のタイムスタンプから秒数ミリ秒を切り捨てて探していた答えを私にくれたと思う。これは、私がデータベース内にある他の条件に対してif文を実行できるようにするはずです。これは問題を攻撃する別の方法ですが、うまくいくと思います。 –

+0

@PatPavお手伝いします! – SqlZim

0

あなたが "TWA" 時間加重平均を探しているなら、この怪物をチェックしてください。私はSCADAパッケージ用のインターフェース用にこれを作った。このクエリでは、標準的な1分、1日、1時間の間隔に限定されません。 @iを変更して、これまでどおりの間隔を得ることができます。クエリの主な仕事は、テーブルに存在する場合に欠落した間隔を処理することです。あなたが午前1時に値を持っていて、午前8時まで別の値を持っていなかったらI.E ...

注:最終選択ステートメントを削除し、何が起きているのかを見るためにCOMBINEを最終選択ステートメントにします。以下の内容をコピーしてSQL Serverに直接貼り付けて、変更せずに実行することができます。 あなたのケースでは、@ iを1に変更して、幸運を祈る。

--Create the test table! Add any values you want! 
DECLARE @TEST001 TABLE (Time_Stamp datetime, TagA INT, TagB INT, TagC INT, TagD INT, TagE INT, TagF INT) 
-- Insert test Values so we can test what is going on with the monster query below.  
INSERT INTO @TEST001 
VALUES 
    ('2017-01-21 00:01:09.042', NULL, NULL, NULL, 7000, NULL, NULL), 
    ('2017-01-21 00:02:03.042', NULL, NULL, 87, NULL, NULL, NULL), 
    ('2017-01-21 00:04:10.155', NULL, 1239, NULL, NULL, NULL, NULL), 
    ('2017-01-21 00:04:10.959', NULL, NULL, 86, NULL, NULL, NULL), 
    ('2017-01-21 00:06:49.401', NULL, 1240, NULL, NULL, NULL, NULL), 
    ('2017-01-21 00:06:59.301', 100, 1239, NULL, NULL, NULL, NULL), 
    ('2017-01-21 00:07:00.000', 109, NULL, NULL, NULL, NULL, NULL), 
    ('2017-01-21 00:07:10.124', 108, NULL, NULL, NULL, NULL, NULL), 
    ('2017-01-21 00:12:11.789', 109, NULL, NULL, NULL, NULL, NULL), 
    ('2017-01-21 00:16:12.190', 108, NULL, NULL, NULL, NULL, NULL), 
    ('2017-01-21 00:16:13.987', 107, NULL, NULL, NULL, NULL, NULL), 
    ('2017-01-21 00:17:31.410', NULL, 1260, NULL, NULL, NULL, NULL), 
    ('2017-01-21 00:17:32.511', NULL, 1261, 87, NULL, NULL, NULL), 
    ('2017-01-21 00:17:32.966', NULL, 1262, NULL, NULL, NULL, NULL), 
    ('2017-01-21 00:18:53.140', NULL, 1262, NULL, NULL, 6000, NULL) 

-- Begin of our query. NOTE to Tech's, The above is not needed WHEN using real table data. 
-- To query real data change #TEST001 to your real table data. and TagA to your desired column. 
declare @s DATETIME2 --Start date and time 
declare @e DATETIME2 --End date and time 
declare @i INT -- Holds our desired interval. if you set to 60 you will get hour intervals, set to 1440 to get daily intervals. 
       -- set to 120 for every two hours 
       -- set to 2880 for every 2 days... 
set @s = '2017-01-21 00:00:00.000' 
set @e = '2017-01-21 23:59:59.000' 
set @i = 60 

--TIME GENERATOR, Generates all times between our start and end date. 
;WITH ALL_INTERVALS 
AS (
    SELECT TOP (DATEDIFF(MINUTE,@s,@e)) 
    TIMES = DATEADD(MINUTE,CONVERT(INT, ROW_NUMBER() OVER (ORDER BY s1.[object_id])-1),@s), 
    NULL AS VALUE 
     FROM sys.all_objects AS s1 
     CROSS JOIN 
     sys.all_objects AS s2 
), 
--Union All possable times from our generator with all real data from our table. 
ALL_TIMES 
AS (
SELECT 
     H.Time_Stamp as TIMES, 
     H.TagA AS VALUE 
    FROM @TEST001 H 
    WHERE Time_Stamp BETWEEN @s and @e 
    UNION ALL 
    SELECT 
     AI.TIMES AS TIMES, 
     AI.VALUE AS VALUE 
     FROM ALL_INTERVALS AI   
), 
-- We need to fill across, up and down. 
-- TIMES=AT.TIMES, just inCASE our generated time is equal to our real data time. 
-- TIMES>AT.TIMES Fill nulls in the upward dirrection. 
-- TIMES>AT.TIMES Fill nulls in the downward dirrection. 
FILL_UP_DOWN_ACCROSS 
AS ( 
    SELECT 
    TIMES AS TIMES, 
    VALUE AS VALUE1, 
    ISNULL(AT.VALUE, (SELECT TOP 1 VALUE FROM ALL_TIMES WHERE TIMES = AT.TIMES AND VALUE IS NOT NULL ORDER BY TIMES ASC)) AS VALUE2, 
    ISNULL(AT.VALUE, (SELECT TOP 1 VALUE FROM ALL_TIMES WHERE TIMES > AT.TIMES AND VALUE IS NOT NULL ORDER BY TIMES ASC)) AS VALUE3, 
    ISNULL(AT.VALUE, (SELECT TOP 1 VALUE FROM ALL_TIMES WHERE TIMES < AT.TIMES AND VALUE IS NOT NULL ORDER BY TIMES DESC)) AS VALUE4 
    FROM ALL_TIMES AT 
), 
-- COMBINE, Select all non null values. The value1,2,3 can be removed! As they are not needed in the final select statement. 
-- I just have them here for quickly viewing what is going on if i make this COMBINE statement as my final select statement. 
COMBINE 
AS (
SELECT TIMES, 
     VALUE1, 
     VALUE2, 
     VALUE3, 
     VALUE4, 
     COALESCE(CASE WHEN FUDA.VALUE2 IS NULL AND FUDA.VALUE4 IS NULL THEN (FUDA.VALUE3) ELSE FUDA.VALUE2 END, 
        CASE WHEN FUDA.VALUE2 IS NULL AND FUDA.VALUE3 IS NULL THEN (FUDA.VALUE4) ELSE FUDA.VALUE2 END, 
        CASE WHEN FUDA.VALUE2 IS NULL AND FUDA.VALUE4 IS NOT NULL THEN (FUDA.VALUE4) ELSE FUDA.VALUE2 END 
       ) AS VALUE5 
     FROM FILL_UP_DOWN_ACCROSS FUDA 
) 
--Final Select Statement, do the TWA! 
--DO TIME WEIGHED AVERAGE. 
SELECT DATEADD(MINUTE,((DATEDIFF(MINUTE,@s,TIMES)/@i)*@i),@s) AS TIMES, 
SUM(CONVERT(FLOAT,CAST(TIMES AS DATETIME)) * VALUE5)/SUM(CONVERT(FLOAT,CAST(TIMES AS DATETIME))) AS TagAvg 
FROM COMBINE 
GROUP BY DATEADD(MINUTE,((DATEDIFF(MINUTE,@s,TIMES)/@i)*@i),@s) 
ORDER BY DATEADD(MINUTE,((DATEDIFF(MINUTE,@s,TIMES)/@i)*@i),@s) 
関連する問題