0
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

The output should be just CIRCUIT2

The values of voltage for CIRCUIT1 varies only 2 times The values of voltage for CIRCUIT2 varies 4 times The values of voltage for CIRCUIT3 varies only 2 times even though the variation is high

Can anyone please tell me how do I proceed to write an sql query which will output CIRCUIT2 as the answer ?

(I have added one more column TIMESTAMP)

Dharman
  • 30,962
  • 25
  • 85
  • 135
Shanthi
  • 637
  • 2
  • 7
  • 17

3 Answers3

0

Here is one way to this(not sure this is the best way to do it in 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) 

Idea here is finding the previous voltage value for each record in source then using conditional aggregation counting the records only when there is a change in current record from previous record.

This is much much easier with window function http://rextester.com/PJFL7743

Pரதீப்
  • 91,748
  • 19
  • 131
  • 172
0

I would suggest the following:

  • Find the previous volaage
  • Count the number of times it is different
  • Aggregate by this count
  • Choose the "n" rows with the fewest values

This looks like:

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;

This orders all the sources by the number of changes. Add a limit to the outer query to get just the top 1.

Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786
0

I ended up using the 2nd solution mentioned here.

https://stackoverflow.com/a/6565970/522882 and then using a group by and count() and then ordering by the count() and limiting the result to 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 ;

Thanks everyone for the replies.

Shanthi
  • 637
  • 2
  • 7
  • 17