1

次の 2 つのテーブルを検討してください。

key_names
----------------------------------------------
id | name
----------------------------------------------
1    Outside Temperature
2    Inside Temperature
3    Relative Humidity 

key_values
----------------------------------------------
id | time                    | key_id | value
----------------------------------------------
1    2013-06-04 13:20:16.347   1        50
2    2013-06-04 13:20:16.348   2        30
3    2013-06-04 13:20:16.349   3        10
4    2013-06-04 13:20:31.120   1        55
5    2013-06-04 13:20:31.122   2        29
6    2013-06-04 13:20:31.120   3        11

値は、3 つの異なるキーに対して 15 秒間隔でデータベースに書き込まれます。1分、5分、1時間などの間隔で値を取り出せるようにしたい。

これは、5分間の間隔で私が今持っているものです:

SELECT time, key_name, value
FROM key_values kv
JOIN key_names kn ON kv.key_id = kn.id
WHERE (key_id = 1 OR key_id = 2 OR key_id = 3)
    AND time >= '2013-06-04 12:20:30' 
    AND time < '2013-06-04 13:20:30'
GROUP BY DATEPART(YEAR, time), DATEPART(MONTH, time), DATEPART(DAY, time),
    DATEPART(HOUR, time), (DATEPART(MINUTE, time) / 5), kv.key_id, kn.key_name
ORDER BY kv.time DESC

もちろん、このクエリでは次のエラーが表示されます。

列 'key_values.time' は、集計関数にも GROUP BY 句にも含まれていないため、選択リストでは無効です。

しかし、集計データは必要ありません。5 分間隔で行の実際の値が必要です。このクエリを修正するにはどうすればよいですか?

予想される結果セット: (5 分間隔)

----------------------------------------------------
time                | key_id | value
----------------------------------------------------
2013-06-04 13:20:16   1        50
2013-06-04 13:20:16   2        30
2013-06-04 13:20:16   3        10
2013-06-04 13:15:16   1        ...
2013-06-04 13:15:16   2        ...
2013-06-04 13:15:16   3        ...
2013-06-04 13:10:16   1        ...
2013-06-04 13:10:16   2        ...
2013-06-04 13:10:16   3        ...
...                   ...      ...

私の質問に答える男の一人のために:

SELECT time, key_name, value
FROM (
        SELECT time, key_name, value, ROW_NUMBER() over (partition by convert(varchar(16), time, 121) order by time desc) as seqnum
        FROM key_values kv
        JOIN key_names kn ON kn.id = kv.tag_id
        WHERE (key_id = 1 OR key_id = 2 )
                AND time >= '2013-06-04 12:20:30' AND time < '2013-06-04 13:20:30'
) k
where seqnum = 1;


Its only returning one of the keys..

2013-06-04 12:20:59.577 Outside Temperature     45
2013-06-04 12:21:59.607 Outside Temperature     45
2013-06-04 12:22:59.637 Outside Temperature     45
2013-06-04 12:23:59.687 Outside Temperature     45
2013-06-04 12:24:59.697 Outside Temperature     46
2013-06-04 12:25:59.723 Outside Temperature     46
4

1 に答える 1

5

この関数を使用してrow_number()、各間隔の値を列挙します。次に、最後のものまたは最初のものを取得します-間隔の直前または最初の前のどちらが必要かによって異なります。

1 分間隔の例を次に示します。

select time, key_name, value
from (SELECT time, key_name, value,
             ROW_NUMBER() over (partition by key_name, convert(varchar(16), time, 121) order by time desc) as seqnum
      FROM key_values kv join
           key_names kn
           ON kv.key_id = kn.id
     ) k
where seqnum = 1;

convert(varchar(16), time, 121)は、(切り捨てを使用して) 最も近い分に日付をフォーマットしています。

編集: その他のインクリメント。次の例は、15 分間のスパンでこれを行う方法を示しています。

(partition by key_name, datediff(minute, 0, time)/15 order by . . . )

5 分単位の場合は、5の代わりに使用15します。これは、時間の始まりからの分数を計算しています(データベース的に言えば)。SQL Server は整数除算を行うため、整数で除算すると期間の識別子が作成されます。minute他の単位については、をhourseconddaymonth、またはに置き換えることができますyear

元のクエリについては、そのconvert()方が理解しやすいと考えました。

于 2013-06-04T14:14:54.037 に答える