2017-04-27 109 views
2

好吧,當談到SQL時,我有些不高興。事實上非常如此,所以我很抱歉,如果這是不言而喻的。SQL:設置AVG時,上一列爲空()

我試圖找出從數據庫3件事情(此表是一個日誌每封郵件的發送):

  • 回覆數時間
  • 總覺得是在10分鐘的回帖#
  • 平均回覆時間

這裏是我的SQL:

 SELECT 
      *, SUM(case when tmp.reply_time <= 10 then 1 else 0 end) as under_10_mins, 
      COUNT(tmp.reply_time) AS total_replies 
     FROM 
      (SELECT 
       TIMESTAMPDIFF(MINUTE, `date`, reply_date) as reply_time 
      FROM 
       tme_email_staff_reply sr 
      JOIN 
       tme_user u 
      ON 
       u.id = sr.staff_id 
      JOIN 
       tme_email_message m 
      ON   
       m.id = sr.message_id 
        WHERE 
       `reply_date` >= '2017-04-01 00:00:00' 
      AND 
       `reply_date` < '2017-04-27 00:00:00' 
      ) 
     AS tmp 

,輸出:

| reply_time | under_10_mins | total_replies | 
    |  106 |   165 |   375 | 

現在,當我在補充:

 SELECT 
      *, SUM(case when tmp.reply_time <= 10 then 1 else 0 end) as under_10_mins, 
      COUNT(tmp.reply_time) AS total_replies 
     FROM 
      (SELECT 
       TIMESTAMPDIFF(MINUTE, `date`, reply_date) as reply_time, 
       (AVG(TIMESTAMPDIFF(SECOND, `date`, reply_date))/60) AS average_reply_time 
      FROM 
       tme_email_staff_reply sr 
      JOIN 
       tme_user u 
      ON 
       u.id = sr.staff_id 
      JOIN 
       tme_email_message m 
      ON   
       m.id = sr.message_id 
        WHERE 
       `reply_date` >= '2017-04-01 00:00:00' 
      AND 
       `reply_date` < '2017-04-27 00:00:00' 
      ) 
     AS tmp 

我的反應是:

| reply_time | average_reply_time |under_10_mins | total_replies | 
    |  106 |  149.08626667 |   0 |    1 | 

正如你所看到的,under_10_minstotal_replies領域已經改變。

架構爲表的鏈接:

tme_email_staff_reply:

id | staff_id | message_id |   reply_date | 
    1 | 234,221,001 | 15fg16d5dgw2 | 2017-04-01 09:34:16 | 

tme_user

id | username | password | email | dob | gender | 
    // data omited 

tme_email_message

id | thread_id | From | To | subject | message | message_id 
    // data omited 

有誰能告訴我爲什麼這樣嗎?以及如何解決它?

+0

什麼是表的架構? –

+0

@SloanThrasher - 一秒鐘,會加。 – JamesG

回答

2

這是爲什麼?

讓我們來看看AVG

AVG([DISTINCT]表達式)

返回expr的平均值。 DISTINCT選項可用於返回expr的不同值的平均值。

如果沒有匹配的行,則AVG()返回NULL。

和DOC在13.19.1 Aggregate (GROUP BY) Function Descriptions也說:

如果你在不包含GROUP BY子句的語句中使用的一組功能,它相當於對所有行分組。有關更多信息,請參閱Section 13.19.3, 「MySQL Handling of GROUP BY」

這意味着在你的子查詢中,您使用avg沒有group by,這將avg所有行,然後在子查詢返回一行。

如何解決?

我想你應該從子查詢移動avg到外部查詢:

SELECT 
    SUM(case when tmp.reply_time <= 10 then 1 else 0 end) as under_10_mins, 
    COUNT(tmp.reply_time) AS total_replies, 
    AVG(average_reply_time) AS average_reply_time 
FROM 
    (SELECT 
     TIMESTAMPDIFF(MINUTE, `date`, reply_date) as reply_time, 
     (TIMESTAMPDIFF(SECOND, `date`, reply_date))/60 AS average_reply_time 
    FROM 
     tme_email_staff_reply sr 
    JOIN 
     tme_user u 
    ON 
     u.id = sr.staff_id 
    JOIN 
     tme_email_message m 
    ON   
     m.id = sr.message_id 
      WHERE 
     `reply_date` >= '2017-04-01 00:00:00' 
    AND 
     `reply_date` < '2017-04-27 00:00:00' 
    ) 
AS tmp 
+0

這對我有效。謝謝。另外,感謝您將我鏈接到某些內容。非常感激。 – JamesG

+0

請注意:'reply_time'對外部查詢沒有意義,它是來自'reply_time'嵌套表的隨機值。我發佈了您的答案**服務器可以自由選擇每個組的任何值。**我投票直到您刪除解決方案提案或您修復它。 SRR。 – danihp

+0

@danihp我刪除'reply_time',這似乎是無用的。而且,你的贊同是從我這裏得到的。 – Blank

1

問題是因爲在您的嵌套查詢中,您引用的是未在5.7.5版本的MySQL版本上的GROUP BY子句中命名的非聚合列。請參閱文檔,注意:The server is free to choose any value from each group

MySQL < 5.7.5允許這種語法,但有特殊的行爲(你的情況):

的MySQL擴展了標準SQL使用GROUP BY的,這樣的選擇列表可參考在GROUP BY子句中未命名的非聚合列。通過避免不必要的列排序和分組,您可以使用此功能獲得更好的性能。但是,這非常有用,因爲每個未在GROUP BY中命名的非聚合列中的所有值對於每個組都是相同的。服務器可以自由選擇每個組中的任何值,因此除非它們相同,否則所選值是不確定的。此外,每個組的值的選擇不能通過添加ORDER BY子句來影響。結果集排序在選擇值後發生,並且ORDER BY不會影響服務器選擇的每個組中的哪些值。

MySQL >= 5.7.5允許此語法,並檢查函數相關:

MySQL的5.7.5和高達工具檢測功能的依賴。如果啓用了ONLY_FULL_GROUP_BY SQL模式(默認情況下),MySQL會拒絕選擇列表,HAVING條件或ORDER BY列表引用既未在GROUP BY子句中命名也未在功能上依賴於它們的非聚合列的查詢。

+0

請問我能爲這個外行解釋你嗎?我很掙扎,因爲我沒有使用GROUP BY ....:/ – JamesG