2017-10-06 264 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