【问题标题】:Calculate a SUM of the SUM of columns in MYSQL计算 MYSQL 中列的 SUM 的 SUM
【发布时间】:2020-10-02 09:38:08
【问题描述】:

我想获得另一列,其中包含任何用户使用的字符的百分比。

要做到这一点,我需要在他/她的 posts.title 和 posts.body 中获取用户所有帖子的总字符数,然后对所有用户的所有字符求和。

我得到了这张桌子:

'name', 'chars_title', 'chars_body', 'chars_total'
'user1', '7', '6', '13'
'user2', '27', '23', '50'
'user3', '6', '5', '11'

使用此查询:

SELECT users.name,
   sum(length(posts.title)) as chars_title, 
   sum(length(posts.body)) chars_body, 
   sum(length(posts.title)+length(posts.body)) chars_total
FROM test.posts posts
JOIN test.users users
ON posts.user_id=users.id
GROUP BY users.name
ORDER BY chars_total DESC;

我可以通过 chars_total 和一个给我总计 char_total 的函数来获取用户使用的 char 的百分比吗?

例如一个函数在已经聚合的列上求和 13+50+11?

【问题讨论】:

  • 思考解决方案可能只是一个子查询。

标签: mysql sum aggregate


【解决方案1】:

你可以CROSS JOIN这个查询:

SELECT SUM(LENGTH(title) + LENGTH(body)) total FROM posts 

返回表中所有用户的总字符数:

SELECT u.name,
       p.chars_title,
       p.chars_body,
       p.chars_title + p.chars_body chars_total,       
       100.0 * (p.chars_title + p.chars_body) / c.total percentage
FROM users u
INNER JOIN (
  SELECT user_id,
         SUM(LENGTH(title)) chars_title, 
         SUM(LENGTH(body)) chars_body
  FROM posts 
  GROUP BY user_id
) p ON p.user_id = u.id
CROSS JOIN (SELECT SUM(LENGTH(title) + LENGTH(body)) total FROM posts) c

请注意,也许您应该使用CHAR_LENGTH() 而不是LENGTH()

【讨论】:

  • 我这种方式有错误,需要更好的检查一下。
  • @Salvio 我已经纠正了错别字。查询语法正确:db-fiddle.com/f/tBHJs6dhp6YFCH4R9FNgov/0
  • 我找到了我发布的另一个解决方案:创建一个临时表并将总数放入一个变量中以在最终查询中使用它。你觉得哪个更便宜? @forpas?
  • 该评论是对另一个用户(现已删除)评论的回答,所以我也必须删除它。
  • 您必须测试性能。 MySql 允许在没有 ON 子句的情况下进行 INNER 连接(实际上是 CROSS JOIN)。
【解决方案2】:

如果您使用的是 MySQL 8+,那么您可以在这里使用SUM() 作为解析函数:

SELECT
    u.name,
    SUM(LENGTH(p.title)) chars_title, 
    SUM(LENGTH(p.body)) chars_body, 
    SUM(LENGTH(p.title) + LENGTH(p.body)) chars_total,
    100.0 * SUM(LENGTH(p.title) + LENGTH(p.body)) /
        SUM(SUM(LENGTH(p.title) + LENGTH(p.body))) OVER ()
        AS chars_total_pct
FROM test.posts p
INNER JOIN test.users u
    ON p.user_id = u.id
GROUP BY
    u.name
ORDER BY
    chars_total DESC;

【讨论】:

  • 和 MYSQL 5.7+?
  • ...你能升级吗? :-)
  • 不幸的是我不能,这是一个遗留项目。
【解决方案3】:

目前我是这样解决的:

1)我已经创建了一个临时表来放置第一个查询结果:

CREATE TEMPORARY TABLE IF NOT EXISTS total SELECT users.name,
   sum(length(posts.title)) as chars_title, 
   sum(length(posts.body)) chars_body, 
   sum(length(posts.title)+length(posts.body)) chars_total
FROM test.posts posts
JOIN test.users users
ON posts.user_id=users.id
GROUP BY users.name
ORDER BY chars_total DESC;

2)计算临时表上的总和并将其放入变量中:

SELECT sum(chars_total) FROM total INTO @total_chars;

3)使用变量查询临时表:

SELECT name, 
       chars_title, 
       chars_body, 
       chars_total, 
       ROUND(chars_total*100/@total_chars, 0) as percentage
FROM total;

我认为这是一个有点脏的解决方案,但现在还可以。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-04
    • 2017-10-31
    • 2018-01-07
    • 1970-01-01
    • 2023-01-12
    相关资源
    最近更新 更多