Получение SUM () хлопков и одновременный подсчет закладок в одном запросе - PullRequest
0 голосов
/ 26 октября 2019

Я испробовал множество решений, похожих на мою проблему, но у меня никто не работал.

У меня есть 5 таблиц:

ПОЛЬЗОВАТЕЛИ таблица:

+----+-------+----------------+-------------+------------+
| id |  name |     email      |    password |  register  |
+----+-------+----------------+-------------+------------+
|  1 | lofy  | hello@hi.com   |         123 | 2019-05-06 |
|  2 | jake  | jake@joke.com  |         123 | 2019-06-22 |
|  3 | moly  | moly@liky.com  |         123 | 2019-05-15 |
+----+-------+----------------+-------------+------------+

POSTS таблица:

+----+-------+-------------------+--------------+------------+
| id | title |       body        |    writer_id |    date    |
+----+-------+-------------------+--------------+------------+
|  1 | lofy  | blah blah blah..  |            1 | 2019-05-06 |
|  2 | jake  | blah blah blah..  |            2 | 2019-06-22 |
|  3 | moly  | blah blah blah..  |            2 | 2019-05-15 |
+----+-------+-------------------+--------------+------------+

ЗАКРЫТА таблица:

+---------+-----------+
| user_id |   post_id |
+---------+-----------+
|       1 |         1 |
|       2 |         2 |
|       3 |         2 |
+---------+-----------+

CLAPS таблица:

+---------+-----------+------------+
| user_id |   post_id | claps_times|
+---------+-----------+------------+
|       1 |         1 |          5 |
|       2 |         2 |         13 |
|       3 |         2 |          7 |
+---------+-----------+------------+

Я использовал этот запрос, чтобы получить подробности сообщений + имя пользователя и аватар +, сколько раз это сообщение было добавлено в закладки пользователями

SELECT 
    posts.*, users.name, users.avatar , 
    COUNT(bookmarks.post_id) AS bookmarksCount   
FROM 
    posts 
LEFT JOIN 
    users ON users.id = posts.owner
LEFT JOIN
    bookmarks ON bookmarks.post_id = posts.id    
GROUP BY 
    posts.id;

Все в порядке, поэтомудалеко.

Проблема: я хотел получить SUM() хлопков для каждого поста, поэтому я добавил еще 2 строки к предыдущему запросу, теперь этот запрос:

SELECT posts.*, users.name, users.avatar , 
    count(bookmarks.post_id) as bookmarksCount ,
    SUM(claps.claps_count) AS totalClaps
    FROM posts 
    LEFT JOIN users ON users.id = posts.owner
    LEFT Join bookmarks ON bookmarks.post_id = posts.id
    LEFT JOIN claps ON claps.post_id = posts.id
    GROUP BY posts.id
    ;

Проблема в том, что результат ударов post.id "2" удваивается, это 40 вместо 20,

Это похоже на объединение count () закладок поста, вызывающеепроблема, другими словами, если сумма () хлопков равняется 10, а пост добавляется в закладки 5 раз после count (), тогда результат хлопков будет 50 вместо 5.

Я пытался подзапросить сумму () хлопков, но я не знал, как это сделать.

Не могли бы вы дать мне решение в виде подзапроса с некоторым объяснением, потому что я добавлюколичество () комментариев позже и, возможно, больше подзапросов

Заранее спасибо

1 Ответ

1 голос
/ 26 октября 2019

Вам нужно объединить перед выполнением объединений. Один из методов:

SELECT p.*, u.name, u.avatar, 
       b.bookmarksCount, c.totalClaps
FROM posts p LEFT JOIN 
     users u
     ON u.id = p.owner LEFT JOIN
     (SELECT b.post_id, COUNT(*) as bookmarksCount
      FROM bookmarks b
      GROUP BY b.post_id
     ) b
     ON b.post_id = p.id LEFT JOIN
     (SELECT c.post_id, SUM(claps_count) as totalClaps
      FROM claps c
      GROUP BY c.post_id
     ) c
     ON c.post_id = p.id;

Обратите внимание, что во внешнем запросе агрегирование не требуется.

Вышеуказанное должно иметь хорошую производительность, если вас интересуют все сообщения. Если вы фильтруете записи по каким-либо критериям, коррелированные подзапросы, вероятно, являются лучшим решением:

SELECT p.*, u.name, u.avatar, 
       (SELECT COUNT(*)
        FROM bookmarks b
        WHERE b.post_id = p.id
       ) as bookmarksCount,
       (SELECT SUM(claps_count)
        FROM claps c
        WHERE c.post_id = p.id
       ) as totalClaps
FROM posts p LEFT JOIN 
     users u
     ON u.id = p.owner LEFT JOIN
      b
     ON b.post_id = p.id;

Для этого вам нужны индексы bookmarks(post_id) и claps(post_id, claps_count).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...