"无效使用群组功能"用于TRUNCATE(SUM())/ TIMESTAMPDIFF查询

时间:2017-09-11 11:19:54

标签: mysql group-by

我有一个包含此架构的数据库:

帖子( id:整数,created_at:datetime,deleted_at:datetime)
posts_reasons( post_id:整数 reason_id:整数
原因( id:整数,权重:整数)

我希望找到SUM为posts.created_at的每个帖子的posts.deleted_atreasons.weight之间的平均时间(也称为删除时间)范围是10.一些样本结果可能是这样的:

  Total Reason Weight (groups of 10)  |  Average Time To Deletion
--------------------------------------+----------------------------
                                   0  |  987.36
                                  10  |  872.01
                                  20  |  819.34
                                  30  |  742.77

等等。我排除了删除时间超过一小时/ 3600秒的帖子,以避免异常值。

这是我到目前为止的查询:

SELECT
  TRUNCATE(SUM(reasons.weight), -1) AS 'Reasons Weight',
  AVG(TIMESTAMPDIFF(SECOND, posts.created_at, posts.deleted_at)) AS 'Avg Time To Deletion'
FROM
  posts
  INNER JOIN posts_reasons ON posts_reasons.post_id = posts.id
  INNER JOIN reasons ON reasons.id = posts_reasons.reason_id
GROUP BY
  posts.id,
  TRUNCATE(SUM(reasons.weight), -1)
HAVING
  posts.deleted_at IS NOT NULL AND
  TIMESTAMPDIFF(SECOND, posts.created_at, posts.deleted_at) <= 3600
ORDER BY
  TRUNCATE(SUM(reasons.weight), -1) ASC;

我已经确定我在WHERE子句中没有聚合函数,因为这个特定问题有多常见;我还确保将查询分组到posts.id,以使SUM(reasons.weight)汇总正常工作。

我仍然无法使用群组功能&#34;错误。我需要做些什么来解决这个问题?

1 个答案:

答案 0 :(得分:1)

您不能在GROUP BY中使用聚合函数!

SELECT
  TRUNCATE(reasons.weight, -1) AS 'Reasons Weight',
  AVG(TIMESTAMPDIFF(SECOND, posts.created_at, posts.deleted_at)) AS 'Avg Time To Deletion'
FROM
  posts
  INNER JOIN posts_reasons ON posts_reasons.post_id = posts.id
  INNER JOIN reasons ON reasons.id = posts_reasons.reason_id
WHERE
  posts.deleted_at IS NOT NULL
  AND TIMESTAMPDIFF(SECOND, posts.created_at, posts.deleted_at) <= 3600
GROUP BY
  TRUNCATE(reasons.weight, -1)
ORDER BY
  TRUNCATE(reasons.weight, -1) ASC;

要进一步按聚合值聚合,可以使用子查询:

SELECT
    ReasonsWeight
  , AVG(TimeToDeletion) AS AvgTimeToDeletion
  , COUNT(*) AS PostCount
FROM
  (
    SELECT
      TRUNCATE(SUM(reasons.weight), -1) AS ReasonsWeight,
      MIN(TIMESTAMPDIFF(SECOND, posts.created_at, posts.deleted_at)) AS TimeToDeletion -- This is per post ID here, aggregation does not matter
    FROM
      posts
      INNER JOIN posts_reasons ON posts_reasons.post_id = posts.id
      INNER JOIN reasons ON reasons.id = posts_reasons.reason_id
    WHERE
      posts.deleted_at IS NOT NULL AND
      TIMESTAMPDIFF(SECOND, posts.created_at, posts.deleted_at) <= 3600
    GROUP BY
      posts.id
  ) AS SRC
GROUP BY
  ReasonsWeight
ORDER BY
  ReasonsWeight ASC
;