SQL Server:计算两列中两个值之间的时间

问题描述 投票:0回答:1

我是SQL Server的新手(到目前为止已有3天的经验,但是我对如何在excel之外完成此操作感到困惑,如果很难解释,对不起。

表格底部示例:

我有一个每分钟带有时间戳,零件计数器和错误代码的表。我目前将零件计数合并到15分钟范围内,并将该范围的总数与以下内容组合在一起:

SELECT
    DATEADD(MINUTE, (DATEDIFF(MINUTE, '20000101', DateTime) / 15) * 15, '20000101') as Date_Time,
    MAX(Part_Count) - MIN(Part_Count) AS PartsMade
FROM 
    [SMP].[dbo].[33_TestImport]
WHERE
    [DateTime] >= DATEADD(HOUR, DATEDIFF(HOUR, 0, GETDATE()) - 24, 0)
GROUP BY
    DATEADD(MINUTE, (DATEDIFF(MINUTE, '20000101', DateTime) / 15) * 15, '20000101')

现在我要添加到此,再添加一行(现在)。

[PV_alarm将成为一个数字,在这一点上,我想计数直到part_count增加的时间,pv_alarm可能在第一次触发和part_count再次增加之间发生多次更改。

so:

  • PV_alarm自然为零
  • PV_alarm变为非零
  • PV_alarm多次更改,最终将以零结束
  • 零件计数增量

要更清楚:表格

DateTime              Part_Count    Alarm_Light PV_Alarm    Runtime_M
-----------------------------------------------------------------------
2020-03-18 20:16:06.040 340946  0   0   127076
2020-03-18 20:17:06.040 340953  0   0   127077
2020-03-18 20:18:06.040 340960  0   0   127078
2020-03-18 20:19:06.040 340967  0   0   127079
2020-03-18 20:20:06.040 340973  0   0   127080
2020-03-18 20:21:06.040 340978  1   8   127081   <--- timer would start here
2020-03-18 20:22:06.040 340978  1   8   127081
2020-03-18 20:23:06.040 340978  1   8   127081
2020-03-18 20:24:06.040 340978  1   8   127081
2020-03-18 20:25:06.040 340978  1   8   127081
2020-03-18 20:26:06.040 340978  1   8   127081
2020-03-18 20:27:06.040 340978  1   8   127081
2020-03-18 20:28:06.040 340978  1   8   127081
2020-03-18 20:29:06.040 340978  1   8   127081
2020-03-18 20:30:06.040 340978  1   8   127081
2020-03-18 20:31:06.040 340978  1   8   127081
2020-03-18 20:32:06.040 340978  1   8   127081
2020-03-18 20:33:06.040 340978  1   8   127081
2020-03-18 20:34:06.040 340978  1   8   127081
2020-03-18 20:35:06.040 340978  1   8   127081
2020-03-18 20:36:06.040 340978  1   8   127081
2020-03-18 20:37:06.040 340978  1   8   127081
2020-03-18 20:38:06.040 340978  1   8   127081
2020-03-18 20:39:06.040 340978  1   8   127081
2020-03-18 20:40:06.040 340978  1   8   127081
2020-03-18 20:41:06.040 340978  1   8   127081
2020-03-18 20:42:06.040 340978  1   8   127081
2020-03-18 20:43:06.040 340978  1   8   127081
2020-03-18 20:44:06.040 340978  1   8   127081
2020-03-18 20:45:06.040 340978  1   8   127081
2020-03-18 20:46:06.040 340978  1   8   127081
2020-03-18 20:47:06.040 340978  1   8   127081
2020-03-18 20:48:06.040 340978  1   8   127081
2020-03-18 20:49:06.040 340978  1   8   127081
2020-03-18 20:50:06.040 340978  1   8   127081
2020-03-18 20:51:06.040 340978  1   8   127081
2020-03-18 20:52:06.040 340978  1   8   127081
2020-03-18 20:53:06.040 340978  1   8   127081
2020-03-18 20:54:06.040 340978  1   8   127081
2020-03-18 20:55:06.040 340978  1   8   127081
2020-03-18 20:56:06.040 340978  1   8   127081
2020-03-18 20:57:06.040 340978  1   8   127081
2020-03-18 20:58:06.040 340978  1   8   127081
2020-03-18 20:59:06.040 340978  1   8   127081
2020-03-18 21:00:06.040 340978  1   8   127081
2020-03-18 21:01:06.040 340978  1   8   127081
2020-03-18 21:02:06.040 340978  1   8   127081
2020-03-18 21:03:06.040 340978  1   8   127081
2020-03-18 21:04:06.040 340978  1   8   127081
2020-03-18 21:05:06.040 340978  1   8   127081
2020-03-18 21:06:06.040 340978  1   8   127081
2020-03-18 21:07:06.040 340978  1   8   127081
2020-03-18 21:08:06.040 340978  1   8   127081
2020-03-18 21:09:06.040 340978  1   8   127081
2020-03-18 21:10:06.040 340978  1   8   127081
2020-03-18 21:11:06.040 340978  1   8   127081
2020-03-18 21:12:06.040 340978  0   0   127081
2020-03-18 21:13:06.040 340978  0   0   127081
2020-03-18 21:14:06.040 340978  0   0   127081
2020-03-18 21:15:06.040 340978  0   0   127081
2020-03-18 21:16:06.040 340978  0   0   127081
2020-03-18 21:17:06.040 340978  0   0   127081
2020-03-18 21:18:06.040 340978  0   0   127081
2020-03-18 21:19:06.040 340978  0   0   127081
2020-03-18 21:20:06.040 340984  0   0   127082    <---- timer ends

结果将是这样,但是如果它也必须是它自己的结果,那么我以后可以与上面的选择结合使用,就可以了

Date_Time               PartsMade   Downtime
2020-03-18 20:45:00.000 0   
2020-03-18 21:00:00.000 0   
2020-03-18 21:15:00.000 68          00:59:00
2020-03-18 21:30:00.000 97  
sql sql-server sql-timestamp
1个回答
0
投票

这里尝试。在this SQLFiddle上查看。

WITH X AS (
SELECT [DateTime], part_count, pv_alarm, case when pv_alarm>0 and (lag(pv_alarm) over (order by DateTime))=0 
               then 'START' else null end as State
from mydata as M1),
XX AS (
SELECT * from X where State IS NOT NULL
),
Y AS (
SELECT [DateTime], part_count, pv_alarm, (lag(part_count) over (order by DateTime)) as prev_part_Count
  from MyData as M2
),
YY AS (
  SELECT Y.[DateTime],Y.part_count,Y.pv_alarm,'END' AS State FROM Y 
  inner join XX on Y.prev_part_count=XX.part_count
  WHERE Y.part_count <> Y.prev_part_count
)
SELECT * FROM XX
UNION ALL SELECT * FROM YY

讨论:

  • CTE X将值[[START分配给行中的列State,其中pv_alarm从上一行的零更改为该行的非零。
  • CTE XX”仅选择分配了State
  • START
  • 的那些行。严格来说,这是没有必要的-可以将其折叠为YY和最终的SELECT-但可以使事情变得更清楚。CTE Y是一个帮助程序,它将上一行的part_count与该行的part count一起带来。您可能会认为它可以折叠为YY,但是LAG()函数必须位于SELECTORDER BY子句中,而不是WHERE子句中。
  • CTE YYY中获取零件数已更改的行,将先前的零件数与CTE X相匹配,以确保我们保持正确的跨度,并分配值
  • END
  • State最后,非CTE选择仅返回
  • START
  • END行。
输出:

DateTime part_count pv_alarm State -------- ---------- -------- ----- 2020-03-18T20:21:06.04Z 340978 8 START 2020-03-18T21:20:06.04Z 340984 0 END

© www.soinside.com 2019 - 2024. All rights reserved.