我有一个表格,其中包含一天中不同时间的信息,但我希望在半小时的周期内为每个项目提取数据。我已经编写了下面的一段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
答案 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;