获取具有特定值的记录数量,但每个唯一字段仅获取一次

时间:2018-09-25 08:26:37

标签: mysql database recordset

我不是在寻找一个完整的答案,但也许有一些指向我应该查看什么样的mysql命令的指针以找出答案。

我有一系列传感器(30+)连接到我的网络。我以不同的时间间隔请求它们的状态,并且每个设备都以n数量的布尔值进行回复,其中n可以是从0到120的任何值(因此响应可以是一个空对象,120个布尔值的列表或介于两者之间的任何数量)。

每个收到的布尔值我都会创建一条新记录,以及设备的mac地址和时间戳。例如(see also this sqlfiddle):

+----+-------------------+---------------------+--------+    
| id | device_address    | timestamp           | status |
+----+-------------------+---------------------+--------+    
|  1 | f2:49:d2:17:5d:8d | 2018-09-22 15:54:51 |      0 |
|  2 | fd:30:ec:08:67:9a | 2018-09-22 15:54:56 |      0 |
|  3 | f8:8d:d9:64:a4:7c | 2018-09-22 15:54:58 |      1 |
|  4 | f2:49:d2:17:5d:8d | 2018-09-22 15:55:51 |      0 |
|  5 | f2:49:d2:17:5d:8d | 2018-09-22 15:55:52 |      0 |
|  6 | fd:30:ec:08:67:9a | 2018-09-22 15:55:56 |      1 |
|  7 | f8:8d:d9:64:a4:7c | 2018-09-22 15:55:58 |      1 |
|  8 | f2:49:d2:17:5d:8d | 2018-09-22 15:56:52 |      0 |
|  9 | f2:49:d2:17:5d:8d | 2018-09-22 15:57:52 |      1 |
| 10 | f2:49:d2:17:5d:8d | 2018-09-22 15:58:52 |      1 |
+----+-------------------+---------------------+--------+

或者,替换为mac地址以提高可读性:

+----+-------------------+---------------------+--------+    
| id | device_address    | timestamp           | status |
+----+-------------------+---------------------+--------+    
|  1 | A                 | 2018-09-22 15:54:51 |      0 |
|  2 | BB                | 2018-09-22 15:54:56 |      0 |
|  3 | CCC               | 2018-09-22 15:54:58 |      1 |
|  4 | A                 | 2018-09-22 15:55:51 |      0 |
|  5 | A                 | 2018-09-22 15:55:52 |      0 |
|  6 | BB                | 2018-09-22 15:55:56 |      1 |
|  7 | CCC               | 2018-09-22 15:55:58 |      1 |
|  8 | A                 | 2018-09-22 15:56:52 |      0 |
|  9 | A                 | 2018-09-22 15:57:52 |      1 |
| 10 | A                 | 2018-09-22 15:58:52 |      1 |
+----+-------------------+---------------------+--------+

最后,我希望能够绘制这些值,并按时间间隔进行分组。例如,当我绘制最近2个小时的数据图时,我想使用5分钟间隔。每个时间间隔,我想知道在此期间至少有一次状态的设备数(唯一)为1,只有零的设备状态为1。完全没有出现在时间段内的设备(因为它们没有返回布尔值)与该时间段无关

以上记录将落在这5分钟的两个时间段内:

  • 15:50:00至15:54:59-id 1 2 3
  • 15:55:00到15:59:59-IDs 4 5 6 7 8 9 10

我想要的回复是这样的:

+---------------------+---------------------------------+-------------------------+    
| timeblock start     | dev w/ at least one status of 1 | dev w/ only status of 0 |
+---------------------+---------------------------------+-------------------------+    
| 2018-09-22 15:50:00 |                               1 |                       2 |
| 2018-09-22 15:55:00 |                               2 |                       1 |
+---------------------+---------------------------------+-------------------------+    

最终结果不必完全像这样,可以帮助我推断这些数字的其他结果也将起作用。时间戳字段也是如此。这种2018-09-22 15:50:00格式会很棒,但其他格式也可以让我扣除时间限制。

执行这样的操作会使我得到不同的时间块以及每个时间块中唯一设备的数量,但是它计算的是1和0的总数,而不是合并每个唯一设备的结果。

SELECT timestamp, 
SUM(status) as ones, COUNT(status)-SUM(status) as zeroes, 
COUNT(DISTINCT(device_address)) as unique_devices 
FROM records 
GROUP BY UNIX_TIMESTAMP(timestamp) DIV 300 
ORDER BY timestamp ASC

结果:

+----------------------+------+--------+----------------+
| timestamp            | ones | zeroes | unique devices |
+----------------------+------+--------+----------------+
| 2018-09-22T15:54:51Z |    1 |      2 |              3 |
| 2018-09-22T15:57:52Z |    4 |      3 |              3 |
+----------------------+------+--------+----------------+

1 个答案:

答案 0 :(得分:1)

使用条件聚合

SELECT timestamp, 
       count(distinct case when status = 1 then device_address end) as ones, 
       count(distinct case when status = 0 then device_address end) as zeros, 
FROM records 
GROUP BY UNIX_TIMESTAMP(timestamp) DIV 300 
ORDER BY timestamp ASC

sqlfiddle demo