我目前正在研究的数据库是用于在某些时间点记录数据的科学仪器。我的仪器每秒记录一次,但分辨率为5秒。
ID Total Particles DateandTime
38313 602 2009-01-27 16:25:48.000
38314 602 2009-01-27 16:25:49.000
38315 602 2009-01-27 16:25:50.000
38316 602 2009-01-27 16:25:51.000
38317 602 2009-01-27 16:25:52.000
38318 553 2009-01-27 16:25:53.000
38319 553 2009-01-27 16:25:54.000
38320 553 2009-01-27 16:25:55.000
38321 553 2009-01-27 16:25:56.000
38322 553 2009-01-27 16:25:57.000
38323 515 2009-01-27 16:25:58.000
38324 515 2009-01-27 16:25:59.000
38325 515 2009-01-27 16:26:00.000
38326 515 2009-01-27 16:26:01.000
38327 515 2009-01-27 16:26:02.000
在某些情况下,这对我们很有用,但与项目的这一部分无关。我想折叠这些数据,以便每5秒钟有一个结果(比如说最后一秒可以保存所有数据用于约定)。
我更喜欢一个没有跳过4行的解决方案并且显示第5行,因为如果我的文章搞砸了并且只在db中给了我4行,那可能无效。我想要的是比较每个样品周围的行和基于此的冷凝的一些方法。
我真的不知道从哪里开始这样的操作,所以任何帮助都会受到赞赏。
答案 0 :(得分:2)
对重复使用通常的ROW_NUMBER()分区,并使用适当的分区方案。
with cte as (
select ID, Total, Particles, DateandTime,
row_number() over (
partition by datediff(seconds,'19000101',DateandTime)/5
order by DateandTime) as rn
from table)
select * from cte
where rn = 1;
无法评论这对于了解表格的确切模式(包括索引)的效率。
答案 1 :(得分:1)
如果流是可预测的,您可以执行以下操作:
select id, particles, time from log where
id in (select min(id) from log group by
datediff(second, (select min(time) from log), time) / 5)
将从每5秒间隔获得第一个读数。第一个间隔覆盖日志中的秒数1 - 5。下一个间隔是秒6-10等,没有重叠。
你可以做一个类似的查询来获得每个区间的平均值,但由于你希望同一区间内的读数相同,所以avg可以在有缺失或错误条目的情况下混合数据,所以只需要第一次或最后一次阅读可能更好。
答案 2 :(得分:1)
我发表评论 - 即使你没有获得5行,我也会假设物理数据点仍然需要5秒钟。如果是这样,以下可能会有效。
首先,创建一个秒函数:
CREATE FUNCTION dbo.GetTotalSeconds(@dt datetime)
RETURNS bigint
AS
BEGIN
RETURN DATEDIFF(ss, '1753-01-01', @dt)
END
现在这个查询:
DECLARE
@StartID int,
@EndID int
SET @StartID = 38313
SET @EndID = 40313
DECLARE @StartSeconds bigint
SELECT TOP 1 @StartSeconds = dbo.GetSeconds(DateandTime)
FROM DataPoints
WHERE ID >= @StartID
ORDER BY ID ASC
SELECT p.ID, p.Total, p.Particles, p.DateandTime
FROM
(
SELECT DISTINCT
(dbo.GetSeconds(DateandTime) - @StartSeconds) / 5 AS SecondsInterval
FROM DataPoints
WHERE ID >= @StartID
AND ID <= @EndID
) g
INNER JOIN DataPoints p
ON (dbo.GetSeconds(p.DateandTime) - @StartSeconds) = g.SecondsInterval
ORDER BY g.SecondsInterval
性能相当弱但它应该处理所有边缘情况。
答案 3 :(得分:1)
好的,所以我有时间将我的MatLab解决方案转换为SQL。不太确定它是否真的那么棒,但效果很好。我的MatLab解决方案花了30多分钟来计算我拥有的220万行的结果,SQL版本用了4分钟!
如果有人在将来遇到类似问题,请参考以下代码:
DECLARE @i INT
DECLARE @Count INT
DECLARE @Selection INT
DECLARE @Result TABLE (ID INT)
SET @i = 1
SET @Count = (SELECT count(*) FROM CFLAPS_AllStations)
WHILE (@i <= @Count)
BEGIN
IF @i < @Count - 4
BEGIN
SET @Selection = (SELECT TotalParticlesCount FROM CFLAPS_AllStations WHERE ID = @i)
IF @Selection = (SELECT TotalParticlesCount FROM CFLAPS_AllStations WHERE ID = @i+4)
BEGIN
INSERT INTO @Result SELECT ID FROM CFLAPS_AllStations WHERE ID = @i
END
ELSE
BEGIN
INSERT INTO @Result SELECT ID FROM CFLAPS_AllStations WHERE ID = @i
SET @i =
CASE
WHEN @Selection = (SELECT TotalParticlesCount FROM CFLAPS_AllStations WHERE ID = @i+3) THEN @i-1
WHEN @Selection = (SELECT TotalParticlesCount FROM CFLAPS_AllStations WHERE ID = @i+2) THEN @i-2
WHEN @Selection = (SELECT TotalParticlesCount FROM CFLAPS_AllStations WHERE ID = @i+1) THEN @i-3
WHEN @Selection = (SELECT TotalParticlesCount FROM CFLAPS_AllStations WHERE ID = @i) THEN @i-4
END
END
END
ELSE
BEGIN
INSERT INTO @Result SELECT ID FROM CFLAPS_AllStations WHERE ID = @i
END
SET @i = @i+5
END
SELECT p.ID, p.TotalParticlesCount, p.FullDateTime FROM CFLAPS_AllStations as p, @Result as q WHERE p.ID = q.ID
所以你们都知道为什么这很重要:仪器总是会记录5秒钟的相同数据,但是如果它停止记录,比如说周期的第二个3;它不会记录第4和第5秒因此出现数据缺口。我设法用这个while循环检查了它,并设法捕获所有这些不一致。
最终输出:
ID TotalParticles DateTime
1 745 2009-06-23 00:00:00.000
6 727 2009-06-23 00:00:05.000
11 771 2009-06-23 00:00:10.000
16 837 2009-06-23 00:00:15.000
21 768 2009-06-23 00:00:20.000
26 703 2009-06-23 00:00:25.000
31 822 2009-06-23 00:00:30.000
36 730 2009-06-23 00:00:35.000
41 731 2009-06-23 00:00:40.000
46 706 2009-06-23 00:00:45.000
51 733 2009-06-23 00:00:50.000
...
2290089 677 2009-06-22 23:59:15.000
2290094 720 2009-06-22 23:59:20.000
2290099 771 2009-06-22 23:59:25.000
2290104 770 2009-06-22 23:59:30.000
2290109 761 2009-06-22 23:59:35.000
2290114 851 2009-06-22 23:59:40.000
2290119 801 2009-06-22 23:59:45.000
2290124 754 2009-06-22 23:59:50.000
2290129 702 2009-06-22 23:59:55.000
感谢所有帮助过的人。
答案 4 :(得分:0)
可能最好的方法(如果你想保留所有'原始'数据)是在插入'raw'表时有一些插入到'summary'表中的触发器。此触发器将根据时间识别传递信息的基础。这意味着你将获得大量数据,但我希望保持它是合适的。值得注意的是,通过触发器执行此操作可能会很糟糕(缓慢),因为每次插入都会发生这种情况。在应用程序级别捕获此信息可能更合适,但我不知道这是否可能......
答案 5 :(得分:0)
感谢您的帮助。我想如果我在这个问题上有更多的时间,我就可以使用你所有的样本并在SQL中直接使用 - 但我真的没有那种自由。我正在研究的项目主要是用MatLab编写的,所以我所做的就是从数据库中提取ID和TotalParticles数据,然后在Matlab中运行对TotalParticles列的检查。此脚本的输出是我对折叠数据库所需的ID值,我将其输入到一个简单的select语句中,然后它将生成我需要的视图。