在MySQL

时间:2017-10-06 20:52:30

标签: mysql sql

我曾经在SQL Server中进行过这种查询。我对MySQL的深度不足。

我希望我能够沟通的是,我希望根据noise_detail和一天中的时间对monitor_id个记录进行分组,但在每一行,我想要每个聚合行的noise_level列的平均值,然后是每个聚合行中count(*)行的平均值。

以下是我们正在跟踪的原始事件的一些示例数据。

OY VEH。严重编辑=再次=解释源数据......

此示例数据中的每一行代表一个“噪音事件”'来自数十个显示器,每个显示器编码为' SEA01,SEA02,SEA03等。)它们每天每小时都会读取数十个读数。

了解在一定日期范围内凌晨3点发生的事件的平均数非常重要。所以:在1月1日凌晨3点在SEA01上进行COUNT()事件,然后在1月2日凌晨3点在SEA01举行COUNT()事件等等,然后给我-average- for所有这些日期。

我们还需要知道每个监视器每小时的平均噪音水平。所以类似地,在1月1日凌晨3点在SEA01上获取事件的AVG(noise_level),然后在1月2日凌晨3点在SEA01上获取事件的AVERAGE(noise_level)等等,然后给我所有那些日期的-average-。

ID    monitor_id    time            noise_level 
393211  SEA14   2016-03-22 15:39:00 79
393245  SEA11   2016-03-05 07:20:00 81.6
338262  SEA15   2016-02-28 19:44:00 80.4
338263  SEA14   2016-02-28 19:55:00 74.2
338264  SEA14   2016-02-28 19:54:00 81.5
338265  SEA14   2016-02-28 19:44:00 73.4
338266  SEA13   2016-02-28 19:54:00 81
338267  SEA13   2016-02-28 19:43:00 94.3
338268  SEA12   2016-02-28 19:43:00 80.2
338269  SEA11   2016-02-28 19:53:00 89
338270  SEA11   2016-02-28 19:43:00 89.5
338271  SEA09   2016-02-28 19:43:00 75.2
338272  SEA09   2016-02-28 19:42:00 73.9
338273  SEA09   2016-02-28 19:41:00 85.1
338588  SEA28   2016-02-29 05:04:00 83.3
338589  SEA22   2016-02-29 05:04:00 82.7
338590  SEA21   2016-02-29 05:04:00 82.9
338591  SEA20   2016-02-29 05:04:00 84.1
338592  SEA19   2016-02-29 05:03:00 88.6
338593  SEA18   2016-02-29 05:03:00 85.5
338594  SEA17   2016-02-29 05:03:00 86.6
338749  SEA14   2016-02-28 20:43:00 83

所以我需要的是看起来像这样:(注意:这是完整报告中的一个样本,它不是从上面的子集中挑选出来的。)

NOISE  REPORT FROM 01/01/2016 - 06/30/2016 SHOWING AVGS FOR EACH HOUR
=================================================
                 avg              avg
monitor_id  hour num_events/hr    noise_level for each hour
SEA11       03AM 12               70.3
SEA11       04AM 55               81.6
SEA11       05AM 27               83.2
SEA11       06AM 16               79.6
....etc.
SEA12       03AM 21               72.7
SEA12       04AM 45               83.1
SEA12       05AM 17               87.9
SEA12       06AM 26               77.6
....etc.

...所以我需要每个监视器/小时一行,其中在一个日期范围内发生在该小时内的平均事件数,然后是-average- noise_level,再次针对每小时发生的所有事件跨越一系列日期。

EG。第6行'发生在1月1日至6月30日凌晨4点的Monitor SEA12'的平均事件数。

这是我到目前为止,它的伪代码'这显然不会起作用,但我希望它能表达我想要实现的目标:

SELECT time, 
       monitor_id, 
       AVG( SELECT COUNT(*) FROM noise_detail nc WHERE nc.monitor_id = n.monitor_id ) AS average_number_of_events,  // avg number of events at X'o'clock
       SELECT AVG(noise_level) FROM noise_detail nl WHERE nl.monitor_id = n.monitor_id) AS average_noise_level  // avg noise level at X'o'clock
FROM noise_detail AS n
GROUP by monitor_id, SUBSTR(time,12,2)  // group by monitor and X'o'clock (the hour of the day in 24 hr format)

2 个答案:

答案 0 :(得分:1)

这是第二次尝试。请注意,使用的数据与问题中的数据不同,请参阅SQL Fiddle

中的此版本

MySQL 5.6架构设置

CREATE TABLE noise_detail 
    (`ID` int, `monitor_id` varchar(5), `time` datetime, `noise_level` int)
;

INSERT INTO noise_detail 
    (`ID`, `monitor_id`, `time`, `noise_level`)
VALUES
    (338271, 'SEA09', '2016-02-24 18:43:00', 75.2),
    (338272, 'SEA09', '2016-02-24 18:42:00', 73.9),
    (338273, 'SEA09', '2016-02-24 18:41:00', 85.1),

    (338271, 'SEA09', '2016-02-24 19:43:00', 75.2),
    (338272, 'SEA09', '2016-02-24 19:42:00', 73.9),
    (338273, 'SEA09', '2016-02-24 19:41:00', 85.1),

    (338271, 'SEA09', '2016-02-25 19:43:00', 75.2),
    (338272, 'SEA09', '2016-02-25 19:42:00', 73.9),
    (338273, 'SEA09', '2016-02-25 19:41:00', 85.1),

    (338271, 'SEA09', '2016-02-26 18:43:00', 75.2),
    (338272, 'SEA09', '2016-02-26 18:42:00', 73.9),
    (338273, 'SEA09', '2016-02-26 18:41:00', 85.1),

    (338271, 'SEA09', '2016-02-26 19:43:00', 75.2),
    (338272, 'SEA09', '2016-02-26 19:42:00', 73.9),
    (338273, 'SEA09', '2016-02-26 19:41:00', 85.1),

    (338271, 'SEA09', '2016-02-28 19:43:00', 75.2),
    (338272, 'SEA09', '2016-02-28 19:42:00', 73.9),
    (338273, 'SEA09', '2016-02-28 19:41:00', 85.1),

    (338271, 'SEA09', '2016-02-28 19:43:00', 75.2),
    (338272, 'SEA09', '2016-02-28 19:42:00', 73.9),
    (338273, 'SEA09', '2016-02-28 19:41:00', 85.1)
;

<强>查询

SELECT
       monitor_id
     , HOUR(time) 
     , COUNT(*)                             as tot_events_in_hour
     , COUNT(*) / COUNT(DISTINCT DAY(time)) as av_events_ph
     , AVG(noise_level)                     AS av_noise_level_in_hour 
     , AVG(noise_level) / COUNT(DISTINCT DAY(time)) AS av_noise_level_ph
FROM noise_detail n
GROUP BY
       monitor_id
     , HOUR(time) 
ORDER BY
       monitor_id
     , HOUR(time) 

<强> Results

| monitor_id | HOUR(time) | tot_events_in_hour | av_events_ph | av_noise_level_in_hour | av_noise_level_ph |
|------------|------------|--------------------|--------------|------------------------|-------------------|
|      SEA09 |         18 |                  6 |            3 |                     78 |                39 |
|      SEA09 |         19 |                 15 |         3.75 |                     78 |              19.5 |

日常/时间数据以人类可读的格式存储是一种常见的误解。列time很可能不会以这种方式存储,因此为字符串设计的substr()不适合确定一天中的小时。你需要日期/时间函数。

SQL Fiddle

MySQL 5.6架构设置

CREATE TABLE noise_detail 
    (`ID` int, `monitor_id` varchar(5), `time` datetime, `noise_level` int)
;

INSERT INTO noise_detail 
    (`ID`, `monitor_id`, `time`, `noise_level`)
VALUES
    (393211, 'SEA14', '2016-03-22 15:39:00', 79),
    (393245, 'SEA11', '2016-03-05 07:20:00', 81.6),
    (338262, 'SEA15', '2016-02-28 19:44:00', 80.4),
    (338263, 'SEA14', '2016-02-28 19:55:00', 74.2),
    (338264, 'SEA14', '2016-02-28 19:54:00', 81.5),
    (338265, 'SEA14', '2016-02-28 19:44:00', 73.4),
    (338266, 'SEA13', '2016-02-28 19:54:00', 81),
    (338267, 'SEA13', '2016-02-28 19:43:00', 94.3),
    (338268, 'SEA12', '2016-02-28 19:43:00', 80.2),
    (338269, 'SEA11', '2016-02-28 19:53:00', 89),
    (338270, 'SEA11', '2016-02-28 19:43:00', 89.5),
    (338271, 'SEA09', '2016-02-28 19:43:00', 75.2),
    (338272, 'SEA09', '2016-02-28 19:42:00', 73.9),
    (338273, 'SEA09', '2016-02-28 19:41:00', 85.1),
    (338588, 'SEA28', '2016-02-29 05:04:00', 83.3),
    (338589, 'SEA22', '2016-02-29 05:04:00', 82.7),
    (338590, 'SEA21', '2016-02-29 05:04:00', 82.9),
    (338591, 'SEA20', '2016-02-29 05:04:00', 84.1),
    (338592, 'SEA19', '2016-02-29 05:03:00', 88.6),
    (338593, 'SEA18', '2016-02-29 05:03:00', 85.5),
    (338594, 'SEA17', '2016-02-29 05:03:00', 86.6),
    (338749, 'SEA14', '2016-02-28 20:43:00', 83)
;

首次查询建议

SELECT
       monitor_id
     , HOUR(time) 
     , COUNT(*) as number_of_events
     , AVG(noise_level) AS average_noise_level 
FROM noise_detail n
GROUP BY
       monitor_id
     , HOUR(time) 
ORDER BY
       monitor_id
     , HOUR(time) 

<强> Results

| monitor_id | HOUR(time) | number_of_events | average_noise_level |
|------------|------------|------------------|---------------------|
|      SEA09 |         19 |                3 |                  78 |
|      SEA11 |          7 |                1 |                  82 |
|      SEA11 |         19 |                2 |                89.5 |
|      SEA12 |         19 |                1 |                  80 |
|      SEA13 |         19 |                2 |                87.5 |
|      SEA14 |         15 |                1 |                  79 |
|      SEA14 |         19 |                3 |             76.3333 |
|      SEA14 |         20 |                1 |                  83 |
|      SEA15 |         19 |                1 |                  80 |
|      SEA17 |          5 |                1 |                  87 |
|      SEA18 |          5 |                1 |                  86 |
|      SEA19 |          5 |                1 |                  89 |
|      SEA20 |          5 |                1 |                  84 |
|      SEA21 |          5 |                1 |                  83 |
|      SEA22 |          5 |                1 |                  83 |
|      SEA28 |          5 |                1 |                  83 |

答案 1 :(得分:0)

这样做你想要的吗?

SELECT time, monitor_id, 
       COUNT(*) as number_of_events,
       AVG(noise_level) AS average_noise_level 
FROM noise_detail nd
GROUP by monitor_id, SUBSTR(time, 12, 2);

我不确定substr(time, 12, 2)应该做什么。如果time存储为字符串,那么很好。如果作为日期/时间数据类型,则使用特定于这些类型的功能。