查询以查找最频繁更改的记录

时间:2017-07-30 06:20:15

标签: mysql sql mysqli

source   |  voltage | timestamp
CIRCUIT1 | 2.4 | XXX
CIRCUIT1 | 2.4 | XXX
CIRCUIT1 | 2.5 | XXX
CIRCUIT1 | 2.4 | XXX
CIRCUIT1 | 2.4 | XXX
CIRCUIT1 | 2.6 | XXX
CIRCUIT1 | 2.4 | XXX
CIRCUIT1 | 2.4 | XXX
CIRCUIT1 | 2.4 | XXX

CIRCUIT2 | 2.4 | XXX
CIRCUIT2 | 2.5 | XXX
CIRCUIT2 | 2.4 | XXX
CIRCUIT2 | 2.4 | XXX
CIRCUIT2 | 2.5 | XXX
CIRCUIT2 | 2.4 | XXX
CIRCUIT2 | 2.5 | XXX
CIRCUIT2 | 2.4 | XXX
CIRCUIT2 | 2.5 | XXX

CIRCUIT3 | 2.4 | XXX
CIRCUIT3 | 2.4 | XXX
CIRCUIT3 | 2.8 | XXX
CIRCUIT3 | 2.4 | XXX
CIRCUIT3 | 2.4 | XXX
CIRCUIT3 | 2.8 | XXX
CIRCUIT3 | 2.4 | XXX
CIRCUIT3 | 2.4 | XXX
CIRCUIT3 | 2.4 | XXX

输出应该只是CIRCUIT2

CIRCUIT1的电压值仅变化2倍 CIRCUIT2的电压值变化4倍 即使变化很大,CIRCUIT3的电压值也只变化2倍

任何人都可以告诉我如何继续编写一个输出CIRCUIT2作为答案的SQL查询?

(我已经添加了一个列TIMESTAMP)

3 个答案:

答案 0 :(得分:0)

这是一种方法(不确定这是在Mysql中执行此操作的最佳方式)

SELECT *
FROM   tabtest
WHERE  source = (SELECT a.source
                 FROM   (SELECT a.source,a.voltage,a.timestamp,Count(*) AS rn
                         FROM   tabtest a
                                JOIN tabtest b
                                  ON a.source = b.source
                                     AND a.timestamp >= b.timestamp
                         GROUP  BY a.source,a.voltage,a.timestamp) a
                        LEFT JOIN (SELECT a.source,a.voltage,a.timestamp,Count(*) AS rn
                                   FROM   tabtest a
                                          JOIN tabtest b
                                            ON a.source = b.source
                                               AND a.timestamp >= b.timestamp
                                   GROUP  BY a.source,a.voltage,a.timestamp) b
                               ON a.source = b.source
                                  AND a.rn = b.rn + 1
                 GROUP  BY a.source
                 ORDER  BY Sum(CASE WHEN a.voltage <> COALESCE(b.voltage, a.voltage) THEN 1 ELSE 0 END) DESC Limit 1) 

这里的想法是找到voltage中每条记录的先前source值,然后使用条件聚合计算记录,只有当前记录中的当前记录发生变化时。

使用窗口函数http://rextester.com/PJFL7743

可以轻松实现这一点

答案 1 :(得分:0)

我建议如下:

  • 查找上一次发生的冲击
  • 计算不同的次数
  • 按此计算汇总
  • 选择值最小的“n”行

这看起来像:

select source, sum(prev_voltage <=> voltage) as changes
from (select t.*,
             (select t2.voltage
              from t t2
              where t2.source = t.source and t2.timestamp < t.timestamp
              order by t2.timestamp desc
              limit 1
             ) prev_voltage
      from t
     ) t
group by source
order by changes;

这会根据更改次数对所有来源进行排序。在外部查询中添加limit以获得前1个。

答案 2 :(得分:0)

我最终使用了这里提到的第二个解决方案。

https://stackoverflow.com/a/6565970/522882然后使用group by和count()然后按计数排序()并将结果限制为1.

           SELECT System, Timestamp, StatusA, StatusB, count(*) as ct
FROM
  ( SELECT (@statusPre <> statusA AND @systemPre=System) AS statusChanged
         , System, Timestamp, StatusA, StatusB
         , @statusPre := StatusA
         , @systemPre := System
    FROM tableX
       , (SELECT @statusPre:=NULL, @systemPre:=NULL) AS d
    ORDER BY System
           , Timestamp
  ) AS good
WHERE statusChanged GROUP BY Systen ORDER BY ct DESC limit 1 ;

感谢大家的回复。