Вычислить сумму СУММЫ столбцов в MYSQL

#mysql #sum #aggregate

#mysql #сумма #агрегировать

Вопрос:

Я хотел бы получить еще один столбец с процентами символов, используемых любым пользователем.

Для этого мне нужно взять общее количество символов, полученных для всех сообщений пользователя в его / ее posts.title и posts.тело суммирует их, а после суммирует все символы всех пользователей.

Я получаю эту таблицу:

 '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?

Например, функция, которая суммирует 13 50 11 по уже агрегированным столбцам?

Комментарии:

1. Размышление о том, может быть, решение — это всего лишь подзапрос.

Ответ №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() .

Комментарии:

1. У меня ошибка таким образом, мне нужно проверить это лучше.

2. @Salvio Я уже исправил опечатки. запрос синтаксически корректен: db-fiddle.com/f/tBHJs6dhp6YFCH4R9FNgov/0

3. Я нашел другое решение, которое я опубликовал: создаю временную таблицу и помещаю сумму в переменную, чтобы использовать ее в конечном запросе. Как вы думаете, что это дешевле? @forpas?

4. Этот комментарий является ответом на (теперь удаленный) комментарий другого пользователя, поэтому я должен удалить его тоже.

5. Вам нужно будет протестировать производительность. MySQL разрешает ВНУТРЕННЕЕ соединение без предложения ON (которое на самом деле является ПЕРЕКРЕСТНЫМ СОЕДИНЕНИЕМ).

Ответ №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;
  

Комментарии:

1. А с MYSQL 5.7 ?

2. …вы можете обновить? :-)

3. К сожалению, я не могу, это устаревший проект.

Ответ №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;
  

Я думаю, что это немного грязное решение, но пока все в порядке.