用MySQL 5.6/7查找局部极小值、极大值和区间样本

用MySQL 5.6/7查找局部极小值、极大值和区间样本,mysql,graph,Mysql,Graph,数据点的单表时间序列(例如功率或温度读数)。 如何有效地选择一个样本来生成包含所有局部极小值、极大值和使用MySQL 5.x对其他数据进行第n次采样的图 其他SQL解决方案使用: 自联接,使用id-1和id+1上的联接,为最大值选择prev.val

数据点的单表时间序列(例如功率或温度读数)。 如何有效地选择一个样本来生成包含所有局部极小值、极大值和使用MySQL 5.x对其他数据进行第n次采样的图

其他SQL解决方案使用:

  • 自联接,使用id-1和id+1上的联接,为最大值选择prev.val为最小值)。这假定有一个连续的唯一ID

  • 使用超前和滞后功能选择上一记录和下一记录的类似逻辑

  • 对ID进行模运算以选择样本,除非偶然选择,否则该样本未达到最大值/最小值

  • MySQL 5.x-在临时表上没有自连接,没有超前和滞后函数,并且此数据没有顺序ID-因此需要使用临时表按顺序重新分配ID

    样本数据:

    id      datetime            val
    194038  2018-07-01 11:30:20 102
    194050  2018-07-01 11:31:40 86
    194054  2018-07-01 11:31:50 101
    194065  2018-07-01 11:33:51 98
    194075  2018-07-01 11:35:50 97
    194085  2018-07-01 11:37:50 99
    194095  2018-07-01 11:39:50 114
    194100  2018-07-01 11:40:40 158
    194105  2018-07-01 11:40:50 116
    194115  2018-07-01 11:41:00 139
    194124  2018-07-01 11:41:30 110
    194128  2018-07-01 11:41:40 121
    194132  2018-07-01 11:41:50 168
    194143  2018-07-01 11:43:51 135
    194153  2018-07-01 11:45:50 128
    194163  2018-07-01 11:47:00 95
    194173  2018-07-01 11:49:00 69
    194186  2018-07-01 11:51:00 64
    194194  2018-07-01 11:51:31 16
    194198  2018-07-01 11:51:41 45
    194209  2018-07-01 11:53:40 60
    194219  2018-07-01 11:55:40 59
    194229  2018-07-01 11:57:40 68
    194246  2018-07-01 11:59:40 67
    
    使用临时表的解决方案是可行的,但效率极低:(参见内联注释)


    有没有更好的方法来做到这一点(或优化这一点)?

    我不了解选择标准对不起-不确定您不了解什么-从一个具有任意日期范围(可能是年-样本是非分层的)的表中,我只想选择足够的数据点来绘制一个合理的图表。它需要包含每N条记录(例如,A.id mod 4=0将其限制为可被4整除的记录)但必须包括所有的波峰和波谷,以便在不借助多项式拟合函数等的情况下,可以看到外围的高点和低点。这是否澄清了?为什么投票失败?我想我会在我的应用程序中处理这种分析。好吧,一点谷歌搜索可以在学习新概念方面创造奇迹。有关初学者,请参见以下SO问题。
    DROP TEMPORARY TABLE IF EXISTS tmp;
    DROP TEMPORARY TABLE IF EXISTS tmp2;
    DROP TEMPORARY TABLE IF EXISTS tmp3;
    DROP TEMPORARY TABLE IF EXISTS tmp4;
    
    # Get data of interest into tmp with sequential ID
    CREATE TEMPORARY TABLE tmp (id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY)
    SELECT datetime, val 
    FROM log
    ORDER BY datetime;
    
    # Make copies of tmp (MySql can't self join on temporary tables)
    CREATE TEMPORARY TABLE tmp2
    SELECT * FROM tmp;
    
    CREATE TEMPORARY TABLE tmp3
    SELECT * FROM tmp;
    
    SELECT A.datetime, A.val
    FROM tmp A, tmp2 P, tmp3 N
    # Join next and previous records (emulates LAG() and LEAD())
    WHERE A.id = P.id + 1
    AND A.id = N.id - 1
    AND (
            (
            # select local maxima
            A.val >= P.val
            AND A.val >= N.val
            )
        OR (
            # select local minima
            A.val <= P.val
            AND A.val <= N.val
            )
        # select a sampling of other records
        # mod value changed by calling code depending on zoom level of graph     
        OR A.id mod 4 = 0
        )
    ORDER BY A.datetime
    
    datetime            val
    2018-07-01 11:31:40 86
    2018-07-01 11:31:50 101
    2018-07-01 11:33:51 98
    2018-07-01 11:35:50 97
    2018-07-01 11:40:40 158
    2018-07-01 11:40:50 116
    2018-07-01 11:41:00 139
    2018-07-01 11:41:30 110
    2018-07-01 11:41:40 121
    2018-07-01 11:41:50 168
    2018-07-01 11:47:00 95
    2018-07-01 11:51:31 16
    2018-07-01 11:51:41 45
    2018-07-01 11:53:40 60
    2018-07-01 11:55:40 59
    2018-07-01 11:57:40 68