2017-10-06 261 views
0

我习惯在SQL Server中进行这种查询。我用MySQL深入了我的视野。在MySQL中结合使用AVG和COUNT

我希望我传达的是,我想组noise_detail记录根据monitor_id和天横跨的日期范围的时间,但在每一行,我则希望noise_level列的每个集合的平均行,然后每个聚合行内的行的平均值为count(*)

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

OY VEH。 HEAVILY EDITED = AGAIN =要解释源数据...

此示例数据中的每一行表示来自数十个监视器的'噪声事件',每个监视器编码为'SEA01,SEA02,SEA03等等)每天有数十次读数。

了解在一定日期范围内3AM发生的事件的平均数量非常重要。因此:在1月1日上午3点在SEA01举办活动COUNT(),然后在1月2日上午3点在SEA01举办活动的COUNT()等,然后为所有这些日期提供“平均数”。

而且我们还需要知道每台显示器每小时的平均噪音水平。因此,同样地,在1月1日上午3点,在SEA01上观看事件的AVG(noise_level),然后在1月2日上午3点在SEA01上观看事件的平均(noise_level)等等,然后给我 - 平均值 - 所有这些日期。

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. 

...所以每个监视器/小时需要一行,并且在一个日期范围内在该小时内发生的平均事件数,然后是 - 平均噪音级别,同样是针对每个日期范围内每个小时发生的所有事件。

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

这里是我迄今为止,它是“伪代码”,这显然是行不通的,但我希望它表达了我想要实现:

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) 
+0

只是因为我在Wordpress和PHP中使用它。如果它不相关,我当然可以删除它。 – jchwebdev

+1

你能提供一些来自每个表格的示例数据,只是为了得到你正在使用的东西吗? –

+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


据该日期/时间数据被存储在一个常见的误解一个人类可读的格式。列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 | 
+0

不,那实际上就是我开始的地方。这只是给出每台监视器/小时的事件总数,我需要在日期范围内3AM发生的事件数量。请看我上面的新的重大编辑。它在主SELECT中需要某种SELECT AVG。 – jchwebdev

+1

你的编辑只是混淆进一步恕我直言。在这种情况下,要澄清这种情况的“诀窍”是将您的样本数据与“预期结果”对齐,应该能够从样本中推导出预期结果。我在这里没有看到。我会尝试别的,也许这会有所帮助。 –

+0

你可能是对的。准备一个'现实'的例子数据集需要一段时间。我希望避免这种情况,因为如果一个人没有立即做出正确的决定,我已经注意到这个论坛字面意思的问题。我不希望这听起来很糟糕,但我从字面上没有意识到这很难解释或'grok'。也许是因为我每天都在做这些东西。谢谢你的帮助。干杯。 – jchwebdev

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); 

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

+0

substr(时间,12,2)sqlfiddle是使小计(组)由 - 小时。您的解决方案不能帮助我。我需要每个监视器/小时总计的平均事件数量。看到我希望更清晰的示例数据。 – jchwebdev