计算表

时间:2018-02-01 22:52:02

标签: mysql sql

  

注意: 我的问题数据在SQLFiddle就在这里   可以查询它。

如何创建表

我有来自表的数据并使用以下逻辑放入临时表,但BETWEEN开始和结束日期时间戳是根据存储过程中的其他逻辑动态生成的。

SET @RowNum = 0;
DROP TEMPORARY TABLE IF EXISTS temp; 
CREATE TEMPORARY TABLE temp AS

SELECT @RowNum := @RowNum + 1 RowNum
        , TimeStr
        , Value        
FROM mytable     
WHERE TimeStr BETWEEN '2018-01-31 06:15:56' AND '2018-01-31 19:27:09'
AND iQuality = 3 ORDER BY TimeStr; 

这给了一个临时表,其行号从最早的基于TimeStr记录开始按顺序递增一个数字,因此最旧的是第一个记录的时间或RowNum 1。

  

临时表

     

enter image description here

数据

您可以访问此临时表数据并在我创建的SQLFiddle上查看此处的查询,但我在那里尝试了一些事情,您会看到哪些内容不在&#39我给了我所需要的东西。

尝试进一步澄清

我需要根据每个集合中的TimeStr值设置每个 ON OFF 的时间,我可以使用{{{ 3}}功能。

我很难弄清楚如何让它给我每个 ON OFF 记录的结果。记录始终按从最旧到最新的顺序排列,行号也始终从1开始。

我有些需要给出每两个记录,其中一个接着RowNum值明智地匹配CycleNum从1开始,每个 ON 增加一个关闭循环或设置。

我可以使用TIMEDIFF(MAX(TimeStr), MIN(TimeStr)) as duration,但我不确定如何最好地按顺序对每两个RowNum记录进行分组,如下所述,为每组提供后续CycleNum值增量。

预期产出

预期输出显示所有 ON OFF 周期的下方屏幕截图或组和序列中的每两个RowNum

TIMEDIFF()

输出澄清

我需要输出包括每个 ON OFF 周期的开始时间,结束时间以及开始和停止之间的持续时间。

enter image description here

3 个答案:

答案 0 :(得分:3)

如果你能保证两件事:

  • 行号严格按顺序排列,没有间隙。
  • 开/关标志始终是交替的。

然后你可以用一个相对简单的join来做到这一点。代码如下:

SELECT (@rn := @rn + 1) as cycle, t.*, tnext.timestr,
       timediff(tnext.timestr, t.timestr)
FROM temp t JOIN
     temp tnext
     ON t.rownum = tnext.rownum - 1 and
        t.value = 1 and
        tnext.value = 0 cross join
     (SELECT @rn := 0) params;

如果这些条件不成立,则需要更复杂的逻辑。

答案 1 :(得分:1)

快速而肮脏的方法就是:

SELECT 
  T1.TimeStr AS StartTime, 
  (SELECT T2.TimeStr FROM temp AS T2 WHERE T2.RowNum = T1.RowNum+1) AS StopTime,
  TIMEDIFF((SELECT T2.TimeStr FROM temp AS T2 WHERE T2.RowNum = T1.RowNum+1),
           T1.TimeStr) AS Duration
FROM temp AS T1
WHERE Value = 1;

似乎必须有更好的方法来做到这一点。两个子查询会很慢。

你可以分两步完成:

CREATE TEMPORARY TABLE startstop AS
SELECT 
  T1.TimeStr AS StartTime, 
  (SELECT T2.TimeStr FROM temp AS T2 WHERE T2.RowNum = T1.RowNum+1) AS StopTime,
  0 AS Duration
FROM temp AS T1
WHERE Value = 1;

UPDATE startstop SET Duration = StopTime - StartTime;

但是我不能在小提琴中测试这个。

答案 2 :(得分:1)

这是一个更简单的方法:

SELECT
  t1.TimeStr AS StartTime, 
  t2.TimeStr AS EndTime, 
  TIMEDIFF(t2.TimeStr, t1.TimeStr) AS Duration  
FROM temp t1
INNER JOIN temp t2 ON t2.RowNum = t1.RowNum + 1
WHERE 
    t2.Value = 0
AND t1.Value = 1