SQL 检索特定日期时间的历史传感器值
Posted
技术标签:
【中文标题】SQL 检索特定日期时间的历史传感器值【英文标题】:SQL Retrieve historical sensor values at specific date times 【发布时间】:2009-01-17 21:12:15 【问题描述】:我有一个数据库,该数据库的血管压力每 30 秒变化一次。我希望能够检索过去几天中特定时间的录音。我无法将其作为存储过程或视图基于服务器——我只有读取权限。我创建了一个过去 17 天的例程,但我希望它能够提供几个月的数据。我猜想只是从 c# 应用程序重复调用,但这似乎比我现在使用的方法效率低。有没有人有什么建议。
布拉德
declare @DeadBand DateTime
declare @EndDate DateTime
declare @End varchar(50)
declare @Start varchar(50)
declare @Temp varchar(50)
declare @NumberDays int
declare @dec int
declare @InnerSqlQry as varchar(8000)
declare @SqlQry as varchar(8000)
SET @NumberDays = 5
SET @dec = @NumberDays
SET @Start = CONVERT(Varchar(30),dateadd(dd,-@NumberDays,GetDate()))
SET @End = CONVERT(Varchar(30),GetDate())
SET @DeadBand= + CONVERT(Varchar(30),dateadd(ss,90,@Start))
SET @Width = + CONVERT(Varchar(30),dateadd(ss,90,@Start))
WHILE (@dec >= 1)
BEGIN
set @InnerSqlQry = ' Select DateTime,ACMKWHYTD_1 From WideHistory Where Datetime >='''+convert(varchar(30), @Start ,120) +''' AND Datetime <= '''+convert(varchar(30),@DeadBand,120) +''' and wwResolution =60000 and wwRetrievalMode = "cyclic" '
if(@dec = 1)
begin
set @SqlQry = @SqlQry+ N' Select top 1 * from openquery(INSQL,''' + REPLACE(@InnerSqlQry, '''', '''''') + ''' )'
end
if((@dec > 1) and (@dec < @NumberDays))
begin
set @SqlQry = @SqlQry+ N' Select top 1 * from openquery(INSQL,''' + REPLACE(@InnerSqlQry, '''', '''''') + ''' ) union '
end
if(@dec = @NumberDays)
begin
set @SqlQry = N' Select top 1 * from openquery(INSQL,''' + REPLACE(@InnerSqlQry, '''', '''''') + ''' ) union '
end
set @dec = @dec - 1
SET @Start = CONVERT(Varchar(30),dateadd(dd,-@dec,GetDate()))
SET @DeadBand= + CONVERT(Varchar(30),dateadd(ss,90,@Start))
END
print(@sqlQry)
exec(@sqlQry)
【问题讨论】:
【参考方案1】:不要使用循环......我认为你也没有。你看过 DatePart 吗?
例如,此查询将获取开始日期和结束日期之间 12:30 发生的每条记录。
Select DateTime,ACMKWHYTD_1 From WideHistory
WHERE DateTime BETWEEN @Start AND @DeadEnd
AND DATEPART(hh,datetime) =12 AND DatePart(mi,datetime)=30
或者,您可以将日期归零,然后使用 datediff 函数比较您的目标时间和您正在寻找的时间之间的分钟数。
其中 ABS(datediff(mi,convert(nvarchar(10),getdate(),8),'10:00PM'))=60 这将为您获取在晚上 10:00 后 60 分钟内发生的所有记录,因此从晚上 9 点到 11 点
【讨论】:
【参考方案2】:我见过很多将 DATETIME 转换为“只是时间”的技巧。事实上,我在那里工作的地方花费了相当长的时间来寻找最快的。人们似乎忘记了“最短代码”并不总是最快的,而且通常包括隐藏的隐式类型转换。我们想出的最快的是......
DATEADD(DAY, DATEDIFF(MINUTE, 0, ), 0)
我提到它的原因是,一旦你有了时间组件,一切都会变得更容易,并且允许更轻松地更改代码以满足细微的不同需求。
DECLARE
@start_date DATETIME,
@end_date DATETIME,
@chosen_time DATETIME
SELECT
@start_date = '2009 Jan 05 00:00',
@end_date = '2009 Jan 12 00:00',
@chosen_time = '1900 Jan 01 17:30' -- '1900 Jan 01' is day 0
SELECT
<whatever>
FROM
WideHistory
WHERE
[WideHistory].DateTime >= @start_date
AND [WideHistory].DateTime < @end_date
AND DATEADD(DAY, DATEDIFF(MINUTE, 0, [WideHistory].DateTime), 0) = @chosen_time
人们可以轻松地将其适应一天中的几个关键时间,或一系列时间等等......
编辑:
正如 cmets 对此答案所述,对数据库结构的更改也将在这里受益。具有 DATE 字段和 TIME 字段。通常是多余的,但在这种情况下可能是有益的。
【讨论】:
@Dems:该 TSQL 代码的唯一问题是与 [WideHistory] 的比较不是 S'argable,因此无法使用索引。 确实,它类似于索引 VARCHAR 字段,然后使用中间 3 个字符连接。出于这个原因,我已经开始在我的表中存储一个 DATE 字段和一个 TIME 字段。甚至 (Date then Time) 的 INDEX 也会带来一些好处,如果需要的话,我可以创建 (Time then Date) INDEX...【参考方案3】:您不能通过将日期时间转换为 unixtime 数字并对其进行修改以提供一天中的时间来更有效地做到这一点。
where 子句会根据您想要的日期范围对其进行过滤,然后 mod 技巧会丢弃所有不在您想要的时间的记录。
然后您可以查询一次,而不是每天查询一次。
【讨论】:
以上是关于SQL 检索特定日期时间的历史传感器值的主要内容,如果未能解决你的问题,请参考以下文章
ORACLE PL/SQL - 使用 SYSDATE 检索特定日期的数据时出现检索问题