Sql server SQL计算特定状态下的总时间
我把这些数据放在一张表格里Sql server SQL计算特定状态下的总时间,sql-server,date,Sql Server,Date,我把这些数据放在一张表格里 _____DateTime____|Variable__|Value 2017/03/29 23:00:00 | Variable1 | 1 2017/03/31 01:00:00 | Variable1 | 0 2017/03/31 02:00:00 | Variable1 | 1 2017/03/31 03:00:00 | Variable1 | 0 2017/03/31 04:00:00 | Variabl
_____DateTime____|Variable__|Value
2017/03/29 23:00:00 | Variable1 | 1
2017/03/31 01:00:00 | Variable1 | 0
2017/03/31 02:00:00 | Variable1 | 1
2017/03/31 03:00:00 | Variable1 | 0
2017/03/31 04:00:00 | Variable2 | 1
2017/03/31 23:00:00 | Variable1 | 1
2017/04/01 01:00:00 | Variable1 | 0
我想计算两个日期之间每个变量处于状态1的总持续时间
例如,Var1 2017/03/31 00:00:00和2017/04/01 00:00:00之间
结果是:
1 hour between 2017/03/31 00:00:00 and 2017/03/31 01:00:00
1 hour between 2017/03/31 02:00:00 and 2017/03/31 03:00:00
1 hour between 2017/03/31 23:00:00 and 2017/04/01 00:00:00
所以我希望Var1的结果应该是3小时
例如,Var2 2017/03/31 00:00:00和2017/04/01 00:00:00之间
结果是:
2017/03/31 04:00:00和2017/04/01 00:00:00之间的1小时之前没有值,但因为它更改为1,我认为它之前为0
所以我想要的Var2的结果应该是20小时
变量| u时间(以秒为单位)
变量1 | 180
变量2 | 1200
如果有人能帮我
由于lead和concat,提前感谢SQL Server 2012+ 使用堆叠cte生成小时表,以内部联接子查询,该子查询使用window函数获取按变量分区的状态更改的下一个日期 为了适应以前的版本,使用外部应用程序获取每个变量的下一个dt,而不是前导;以及使用正确转换而不是concat的常规字符串连接
如果您需要经常这样做,您可以考虑创建一个实际的表数小时。否则,使用堆叠cte与大多数其他选项一样快,并且随着生成的值数量的增加,比递归cte快得多
编号和日历表参考:这总是按小时吗?非常感谢你的回答,它工作得很好。事实上,我只想要每个变量在特定状态下的持续时间,以小时为单位不是一个好主意!!!更正@SqlZim。它不起作用,因为它给了我2017-03-29 23:00:00和2017-03-31 01:00:00之间的时间。因为我的查询是从2017-03-31 00:00:00开始的,所以我只想要2017-03-31 00:00:00和2017-03-31 01:00之间的时间:00@StéphanF更新为使用minh.datehour
declare @fromdate datetime = '20170331 00:00:00';
declare @thrudate datetime = '20170401 00:00:00';
;with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n))
, hours as (
select top ((datediff(hour, @fromdate, @thrudate)+1))
[DateHour]=dateadd(hour,(row_number() over (order by (select 1)) -1),@fromdate)
from n as deka cross join n as hecto cross join n as kilo
cross join n as tenK cross join n as hundredK
order by 1
)
select variable, value
, hours = count(h.datehour)
, start_dt = convert(varchar(20),min(h.datehour),120)
, end_dt = convert(varchar(20),end_dt,120)
, txt = concat(
count(h.datehour),' '
, case when count(h.datehour) < 2 then 'hour' else 'hours' end
, ' between '
, convert(varchar(20),min(h.datehour),120)
, ' and '
, convert(varchar(20),end_dt,120)
)
from hours h
inner join (
select
variable
, value
, start_dt = dt
, end_dt = case when coalesce(lead(dt) over (partition by variable order by dt),@thrudate) > @thrudate
then @thrudate
else coalesce(lead(dt) over (partition by variable order by dt),@thrudate)
end
from t
) s
on h.datehour >= s.start_dt
and h.datehour < s.end_dt
where h.datehour >= @fromdate
and h.datehour < @thrudate
and s.value = 1
group by variable, value, start_dt, end_dt
+-----------+-------+-------+---------------------+---------------------+--------------------------------------------------------------+
| variable | value | hours | start_dt | end_dt | txt |
+-----------+-------+-------+---------------------+---------------------+--------------------------------------------------------------+
| Variable1 | 1 | 1 | 2017-03-31 00:00:00 | 2017-03-31 01:00:00 | 1 hour between 2017-03-31 00:00:00 and 2017-03-31 01:00:00 |
| Variable1 | 1 | 1 | 2017-03-31 02:00:00 | 2017-03-31 03:00:00 | 1 hour between 2017-03-31 02:00:00 and 2017-03-31 03:00:00 |
| Variable1 | 1 | 1 | 2017-03-31 23:00:00 | 2017-04-01 01:00:00 | 1 hour between 2017-03-31 23:00:00 and 2017-04-01 01:00:00 |
| Variable2 | 1 | 20 | 2017-03-31 04:00:00 | 2017-04-01 00:00:00 | 20 hours between 2017-03-31 04:00:00 and 2017-04-01 00:00:00 |
+-----------+-------+-------+---------------------+---------------------+--------------------------------------------------------------+