あなたが "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)
「分平均」とはどういう意味ですか? – iamdave
[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)をこの質問に追加しますか? –
私はタイムスタンプとサンプル値の2つの列を持ち、数秒ごとに記録されるテーブルを持っています。上記のSELECT文を使用して、それらのサンプルの時間平均を取得することができます。私はこれをさらに進歩させ、分の平均を取る必要があります。 –