返回周期性数据

时间:2015-01-08 11:26:07

标签: sql sql-server-2008

我有一个表格,其中包含一天中不同时间的信息,但我希望在半小时的周期内为每个项目提取数据。我已经编写了下面的一段SQL来每半小时撤回一次信息,但是它有一个问题,我似乎无法纠正它!

AND DATEPART(minute, MyTimestamp) in (0, 30)

起初这似乎工作得很好,但当我真正更详细地查看信息时,我意识到它会在以下时间返回数据:

00:00:00
00:00:30
00:30:00
00:30:30

但实际上它应该只返回这些时间:

00:00:00
00:30:00

2 个答案:

答案 0 :(得分:1)

00:00:30的分钟部分是0所以返回它,以消除非零秒添加另一个子句:

where DATEPART(minute, MyTimestamp) in (0, 30) 
  and DATEPART(second, MyTimestamp) = 0

或仅包含以模数30分钟为单位的秒数;

where datediff(second, cast(MyTimestamp as date), MyTimestamp) % 1800 = 0

答案 1 :(得分:0)

您是否确保在一小时内准确输入,准确地在半小时内输入?您关注的是(半小时)后30秒内的输入,但如果这是该时间范围的第一个输入怎么办?

这是一个解决方案,将条目分为半小时段,然后选择每个段的第一个(最早)条目。

首先,我不得不制作一些样本数据。我使用旧的备用,AdventureWorks。 Sales.SalesOrderHeader表具有适合帐单的OrderDate字段,但它没有时间值。所以,让我们供应一些。我选择了数据的第一天,并使用它在 SQL Fiddle 中创建一个测试表,使用随机值填充一些小时,分钟和秒值。

有一天有很多条目。让我们看一下原始数据: SQL Fiddle

ID          OrderDate
----------- -----------------------
43684       2011-05-31 01:14:05.000
43673       2011-05-31 01:20:41.000
43674       2011-05-31 01:40:22.000
43681       2011-05-31 02:00:32.000
...
43688       2011-05-31 20:18:45.000
43672       2011-05-31 21:49:50.000
43693       2011-05-31 22:46:08.000
43670       2011-05-31 23:14:22.000

(43 row(s) affected)

现在让我们将每个时间戳分成半小时段: SQL Fiddle

ID          OrderDate               Hour        HalfHour
----------- ----------------------- ----------- -----------
43684       2011-05-31 01:14:05.000 1           0
43673       2011-05-31 01:20:41.000 1           0
43674       2011-05-31 01:40:22.000 1           1
43681       2011-05-31 02:00:32.000 2           0
....
43688       2011-05-31 20:18:45.000 20          0
43672       2011-05-31 21:49:50.000 21          1
43693       2011-05-31 22:46:08.000 22          1
43670       2011-05-31 23:14:22.000 23          0

(43 row(s) affected)

现在我们可以按小时和半小时字段进行分组,并采用每个时段的最早时间戳: SQL Fiddle

Hour        HalfHour    MinDate
----------- ----------- -----------------------
1           0           2011-05-31 01:14:05.000
1           1           2011-05-31 01:40:22.000
2           0           2011-05-31 02:00:32.000
3           1           2011-05-31 03:56:33.000
....
20          0           2011-05-31 20:18:45.000
21          1           2011-05-31 21:49:50.000
22          1           2011-05-31 22:46:08.000
23          0           2011-05-31 23:14:22.000

(30 row(s) affected)

我们需要完成任务。将一个结果集与另一个结果集连接起来,以获得每个半小时段的第一个条目: SQL Fiddle

这是最终查询。它不完全是你在SQL Fiddle中找到的 - 它是使用AdventureWorks数据库的那个(如果你安装了那个数据库,并且SQL Fiddle正在使用它的一个周期性的混合)。如果您使用AdventureWorks,请记住将值加载到OrderDate字段的时间部分。另请注意,这是写一天。要工作超过一天的时间范围,您必须按天和小时半小时进行分组。

with
ByHalfHour as(
    select  soh.SalesOrderID ID, soh.OrderDate,
            DatePart( HOUR, soh.OrderDate ) as Hour,
            Case when DatePart( MINUTE, soh.OrderDate ) < 30 then 0 else 1 end as HalfHour
    from    Sales.SalesOrderheader soh
    where   soh.OrderDate >= '2011-05-31'
        and soh.OrderDate < '2011-06-01'
),
MinHalfHour as(
    select  Hour, HalfHour, Min( OrderDate ) as MinDate
    from    ByHalfHour
    group by Hour, HalfHour
)
select  bhh.*
from    ByHalfHour  bhh
join    MinHalfHour mhh
    on  mhh.Hour    = bhh.Hour
    and mhh.HalfHour= bhh.HalfHour
    and mhh.MinDate = bhh.OrderDate
order by bhh.Hour, bhh.HalfHour;