【问题标题】:SQL Server difference between values of many irregular measurementsSQL Server 许多不规则测量值之间的差异
【发布时间】:2016-01-28 19:07:58
【问题描述】:

我有一个 SQL 服务器数据库,其中包含一个包含 100 个测量点的测量数据的表。每一个都以大约 5 秒的间隔进行测量。格式如下:

MeasurementPointID           timestamp              value
001234                       03-01-2015 00:02:03    100
001234                       03-01-2015 00:02:08    120
001234                       03-01-2015 00:02:13    130
001234                       03-01-2015 00:02:19    160
001234                       03-01-2015 00:02:22    200
001236                       03-01-2015 00:02:04    400
001236                       03-01-2015 00:02:09    405
001236                       03-01-2015 00:02:14    420
001236                       03-01-2015 00:02:19    445
001236                       03-01-2015 00:02:25    470
Etc.

我想知道如何通过前一个时间戳除以时间段(因为前一个时间戳)后测量值发生变化来制作视图

MeasurementPointID           timestamp              changeDivPeriod
001234                       03-01-2015 00:02:03    0 <-- Zero would be nice here
001234                       03-01-2015 00:02:08    4
001234                       03-01-2015 00:02:13    2
001234                       03-01-2015 00:02:19    5
001234                       03-01-2015 00:02:22    13,333333
001236                       03-01-2015 00:02:04    0 <-- Zero would be nice here
001236                       03-01-2015 00:02:09    1
001236                       03-01-2015 00:02:14    3
001236                       03-01-2015 00:02:19    5
001236                       03-01-2015 00:02:25    4,166666
Etc.

我该怎么做呢?首先用视图解决这个问题是否明智?

我认为将触发器添加到此表并使用计算值填充新表(而不是视图)会更快/更容易。如果是这样,我该怎么做?

【问题讨论】:

  • 40/3 是 13.333333 而不是 10。行(160 和 200)和 3 秒差异
  • 提示:使用适当的软件(MySQL、Oracle、DB2 等)和版本标记数据库问题很有帮助,例如sql-server-2014。语法和功能的差异通常会影响答案。
  • 谢谢。我修复了问题中的错误并添加了额外的标签。

标签: sql sql-server tsql sql-server-2012


【解决方案1】:

你可以使用窗口函数和自连接(如果需要的话,用视图包裹它):

WITH cte AS
(
  SELECT *,
    rn = ROW_NUMBER() OVER (PARTITION BY MeasurementPointID ORDER BY [timestamp])
  FROM #tab
)
SELECT c1.MeasurementPointID,
       c1.[timestamp],
       [changeDivPeriod] = 
           CASE WHEN c1.rn = 1 THEN 0 
                ELSE 1.0 * (c1.[value] - c2.[value]) 
                     / NULLIF(DATEDIFF(second, c2.[timestamp], c1.[timestamp]),0)
           END
FROM cte c1
LEFT JOIN cte c2
  ON c1.MeasurementPointID = c2.MeasurementPointID 
  AND c1.rn = c2.rn+1;

LiveDemo

输出:

╔════════════════════╦═════════════════════╦═════════════════╗
║ MeasurementPointID ║      timestamp      ║ changeDivPeriod ║
╠════════════════════╬═════════════════════╬═════════════════╣
║             001234 ║ 2015-03-01 00:02:03 ║ 0               ║
║             001234 ║ 2015-03-01 00:02:08 ║ 4               ║
║             001234 ║ 2015-03-01 00:02:13 ║ 2               ║
║             001234 ║ 2015-03-01 00:02:19 ║ 5               ║
║             001234 ║ 2015-03-01 00:02:22 ║ 13.333333333333 ║
║             001236 ║ 2015-03-01 00:02:04 ║ 0               ║
║             001236 ║ 2015-03-01 00:02:09 ║ 1               ║
║             001236 ║ 2015-03-01 00:02:14 ║ 3               ║
║             001236 ║ 2015-03-01 00:02:19 ║ 5               ║
║             001236 ║ 2015-03-01 00:02:25 ║ 4.166666666666  ║
╚════════════════════╩═════════════════════╩═════════════════╝

使用SQL Server 2012+,您可以使用LEAD/LAG

SELECT 
  MeasurementPointID,
  [timestamp],
  [changeDivPeriod] =  COALESCE(1.0 * ([value] - LAG ([value]) OVER ( PARTITION BY MeasurementPointID ORDER BY [timestamp] )) 
                               / NULLIF(DATEDIFF(second, LAG ([timestamp]) OVER ( PARTITION BY MeasurementPointID ORDER BY [timestamp]), [timestamp]),0),0)
FROM #tab

LiveDemo2

【讨论】:

  • 非常感谢。奇迹般有效!由于是sql server 2012,我都试过了,第二个要快得多。
猜你喜欢
  • 1970-01-01
  • 2011-03-04
  • 2023-03-08
  • 1970-01-01
  • 2018-04-21
  • 2016-10-21
  • 2014-06-09
  • 2010-09-05
  • 2021-11-10
相关资源
最近更新 更多