MySQL查询使用最少的行作为列和平均值

时间:2017-02-12 11:09:36

标签: mysql

我有一个太复杂的SQL问题(MySQL),我需要帮助。

我有一张温度读数表。这些读数来自放置在不同位置的许多传感器。每个读数都在时间戳上显示。读数每十分钟进行一次,并且由于读数在传感器之间顺序发生,因此各个传感器读数之间可能会有一秒钟。

两个传感器读取外部温度,这意味着每十分钟有两个读数(位置= 5和位置= 6)反映外部温度。这些传感器放在建筑物的北侧和南侧,这意味着两个读数中最低的读数可能是最准确的,因为目前最高的读数可以被阳光照射。

因此该表的样本将如下所示

SELECT * FROM Temperatures 
WHERE timestamp > "2016-07-01 15:00" 
AND timestamp < "2016-07-01 15:40"
AND (Location=5 OR Location=6) 
AND Site=3 
ORDER BY timestamp ASC

(`ReadingID`, `Timestamp`, `Site`, `Location`, `Temperature`)
(3921775, '2016-07-01 15:00:01', 3, 5, 18),
(3921776, '2016-07-01 15:00:02', 3, 6, 17.5),
(3921781, '2016-07-01 15:10:01', 3, 5, 18.6),
(3921782, '2016-07-01 15:10:03', 3, 6, 17.9),
(3921787, '2016-07-01 15:20:01', 3, 5, 18.4),
(3921788, '2016-07-01 15:20:01', 3, 6, 22.7),
(3921793, '2016-07-01 15:30:01', 3, 5, 19.4),
(3921794, '2016-07-01 15:30:02', 3, 6, 29.2);

正如您所看到的,时间戳可能会因位置= 5和位置= 6之间的第二个而有所不同,即使它们具有强时间相关性。 在15:00和15:10,位置6具有最低温度,15:20和15:30位置5具有最低温度。阅读ID在这里无关紧要。

我想要的是以下内容: 1)显示每10分钟间隔的最小位置5和位置6。例如,这个查询将如何查找一天? (让我们考虑“2016-07-01 00:00”到“2016-07-01 23:50”。

IE中。以下

(`Timestamp (as 10 minute interval)`, `Location`, `Min of location 5 and 6`)
'2016-07-01 00:00', <some data>
...
'2016-07-01 15:00', 6, 17.5
'2016-07-01 15:10', 6, 17.9
'2016-07-01 15:20', 5, 18.4
'2016-07-01 15:30', 5, 19.4
...
'2016-07-02 23:50', <some data>

2)在一个月的间隔内,一天的平均室外温度是多少?这是“2016-07-01 00:00”到“2016-07-01 23:50”的平均温度,基于每10分钟读数的位置5和位置6的最低温度。你会怎么写这个查询?

在后一种情况下,让我们假设所有数据都已到位,即。每天确实有144个读数(这种情况大多是这种情况)或者让我们假设如果错过了一个读数,它并不会对平均值产生太大的影响。

EG。需要以下结果:

(`Date`, `Average based on min of location 5 and 6 for each 10 minute intervl`)
'2017-07-01', 12.0
'2017-07-02', 13.1
'2017-07-03', 12.9
etc.
'2017-07-31', 17.7

祝你好运 PAL

2 个答案:

答案 0 :(得分:1)

对于第一个问题,您可以生成一系列日期 - 小时 - 分钟:

(select date_format(TimeStamp1, '%Y-%m-%d %H:%i') as TimeStamp, 
       min(Temperature) as Temperature 
 from Temperatures
 group by date_format(TimeStamp1, '%Y-%m-%d %H:%i')) tserie

并返回时间戳和温度匹配的位置。

select tserie.TimeStamp, Location, tserie.Temperature
from Temperatures
     inner join (select date_format(TimeStamp1, '%Y-%m-%d %H:%i') as TimeStamp, 
                        min(Temperature) as Temperature 
                 from Temperatures
                 group by date_format(TimeStamp1, '%Y-%m-%d %H:%i')) tserie
where date_format(TimeStamp1, '%Y-%m-%d %H:%i') = TimeStamp and tserie.Temperature = Temperatures.Temperature
;

结果如下:

+------------------+----------+-------------+
|     TimeStamp    | Location | Temperature |
+------------------+----------+-------------+
| 2016-07-01 15:00 |     6    |    17,50    |
| 2016-07-01 15:10 |     6    |    17,90    |
| 2016-07-01 15:20 |     5    |    18,40    |
| 2016-07-01 15:30 |     5    |    19,40    |
+------------------+----------+-------------+

对于第二部分,使用两个日期之间的相同时间序列,计算平均温度:

select date_format(Tstamp2, '%Y-%m-%d') as Day, sum(Temperature) / count(*) as Avg
from  (select date_format(TimeStamp1, '%Y-%m-%d %H:%i') as Tstamp2, 
              min(Temperature) as Temperature 
       from Temperatures
       where TimeStamp1 >= '2016-07-01' and TimeStamp1 < '2016-08-01'
       group by date_format(TimeStamp1, '%Y-%m-%d %H:%i')) tserie
group by date_format(Tstamp2, '%Y-%m-%d')
;

结果:

+------------+-----------+
|     Day    |    Avg    |
+------------+-----------+
| 2016-07-01 | 18,300000 |
+------------+-----------+
| 2016-07-02 | 18,300000 |
+------------+-----------+

在此处查看:http://rextester.com/BXJW4041

答案 1 :(得分:0)

您也可以使用此查询获取每10分钟的最小值

SELECT
    DATE_FORMAT(t1.Timestamp, '%Y-%m-%d %H:%i') AS `Timestamp`
    , IF( LEAST(t1.`Temperature`, t2.`Temperature`) = t1.`Temperature`, 
        IF(t1.`Temperature` = t2.`Temperature` , '5/6', 5 ), 6) AS Location
    , LEAST(t1.`Temperature`, t2.`Temperature`) AS Temperature
FROM Temperatures t1
LEFT JOIN Temperatures t2
ON
    t2.Location = 6 
AND
    t2.`TIMESTAMP` 
    BETWEEN 
        t1.`TIMESTAMP` - INTERVAL 5 SECOND
    AND 
        t1.`TIMESTAMP` + INTERVAL 5 SECOND
WHERE t1.Location = 5;

<强>样品

如果两个传感器具有相同的温度,它也会显示。

mysql> select * from Temperatures;
+-----------+---------------------+------+----------+-------------+
| ReadingID | Timestamp           | Site | Location | Temperature |
+-----------+---------------------+------+----------+-------------+
|   3921775 | 2016-07-01 15:00:01 |    3 |        5 |      18.000 |
|   3921776 | 2016-07-01 15:00:02 |    3 |        6 |      17.500 |
|   3921781 | 2016-07-01 15:10:01 |    3 |        5 |      18.600 |
|   3921782 | 2016-07-01 15:10:03 |    3 |        6 |      17.900 |
|   3921787 | 2016-07-01 15:20:01 |    3 |        5 |      18.400 |
|   3921788 | 2016-07-01 15:20:01 |    3 |        6 |      22.700 |
|   3921793 | 2016-07-01 15:30:01 |    3 |        5 |      19.400 |
|   3921794 | 2016-07-01 15:30:02 |    3 |        6 |      29.200 |
|   3921795 | 2016-07-01 15:40:02 |    3 |        5 |      27.120 |
|   3921796 | 2016-07-01 15:40:04 |    3 |        6 |      27.120 |
+-----------+---------------------+------+----------+-------------+
10 rows in set (0,00 sec)

mysql> SELECT
    ->     DATE_FORMAT(t1.Timestamp, '%Y-%m-%d %H:%i') AS `Timestamp`
    ->     , IF( LEAST(t1.`Temperature`, t2.`Temperature`) = t1.`Temperature`,
    ->         IF(t1.`Temperature` = t2.`Temperature` , '5/6', 5 ), 6) AS Location
    ->     , LEAST(t1.`Temperature`, t2.`Temperature`) AS Temperature
    -> FROM Temperatures t1
    -> LEFT JOIN Temperatures t2
    -> ON
    ->     t2.Location = 6
    -> AND
    ->     t2.`TIMESTAMP`
    ->     BETWEEN
    ->         t1.`TIMESTAMP` - INTERVAL 5 SECOND
    ->     AND
    ->         t1.`TIMESTAMP` + INTERVAL 5 SECOND
    ->
    -> WHERE t1.Location = 5;
+------------------+----------+-------------+
| Timestamp        | Location | Temperature |
+------------------+----------+-------------+
| 2016-07-01 15:00 | 6        |      17.500 |
| 2016-07-01 15:10 | 6        |      17.900 |
| 2016-07-01 15:20 | 5        |      18.400 |
| 2016-07-01 15:30 | 5        |      19.400 |
| 2016-07-01 15:40 | 5/6      |      27.120 |
+------------------+----------+-------------+
5 rows in set (0,00 sec)

mysql>