通过过滤来汇总多个表中的多个列

时间:2014-03-14 18:35:29

标签: mysql sql ruby-on-rails sum

我们的用户可以在移动设备和网络上欣赏,保存,分享和创建内容。其中每个操作都由一个包含source列的表格表示,其值为mobileweb

我需要找到最活跃的移动用户,以喜欢,分享,保存和创建的总和来表示。

User has_many Likes, Likes belong_to User
User has_many Shares, Shares belong_to User
User has_many Saves, Saves belong_to User
User has_many Creates, Creates belong_to User

// User Table
id | full_name | email | ...

// Likes, Share, Save, Create Table
id | user_id | source | ...

我的理想输出是:

// ordered by grand total
id | full_name | total likes | total saves | total creates | total shares | grand total

我可以为其中一个操作创建查询:

SELECT u.full_name, u.id, COUNT(*) as "Likes"
FROM users u, likes l
WHERE u.id = l.user_id and l.source = 'mobile'
GROUP BY full_name
ORDER BY COUNT(*) DESC

但我不确定如何在不同的表格中总结他们的所有行动。

我们的users表格包含likes_countsaves_countcreate_count字段,这些字段会在执行每项操作时得到更新,但随着移动和网络活动的增加而增加,如上所述,我只需要手机。它也缺少股票数量,我希望在试图弄清楚我们最活跃的移动用户是谁的时候将其包括在内。

我不知道从哪里开始,因为它似乎是一个非常毛茸茸的查询。

我们正在使用Rails,所以我可以使用基于控制台的解决方案(将转储SQL)。

2 个答案:

答案 0 :(得分:1)

尝试:

SELECT username, ident, SELECT SUM(COUNT(l.id)+count(sa.id)+...)  as Total
FROM(   
  SELECT u.full_name as username, u.id as ident, COUNT(l.id) AS  likes,
       count(sa.id) as saves, ...
  FROM users u, likes l, saves sa, ...
  WHERE u.id = l.user_id and l.source = 'mobile'
  AND (u.id = sa.user_id and sa.source = 'mobile')
  ...
  GROUP BY full_name)
ORDER BY Total DESC

答案 1 :(得分:0)

这是我最终的结果。创建多个虚拟表并以用户的全名加入它们:

SELECT likes_table.full_name,
   COALESCE(likes_count,0) AS likes, 
   COALESCE(saves_count, 0) AS saves, 
   COALESCE(share_count,0) AS shares, 
   COALESCE(create_count,0) AS "create", 
   (COALESCE(likes_count,0) + COALESCE(saves_count,0) + COALESCE(share_count,0) + COALESCE(create_count,0)) AS TOTAL
FROM (
SELECT u.full_name, count(*) AS likes_count 
FROM users u, likes l
WHERE u.id = l.user_id 
AND l.source = 'mobile'
GROUP BY u.full_name) AS likes_table
    LEFT JOIN (
        SELECT u.full_name, COUNT(*) AS saves_count 
        FROM users u, saves s
        WHERE u.id = s.user_id
        WHERE s.source = 'mobile' 
        GROUP BY u.full_name) AS saves_table 
    ON likes_table.full_name = saves_table.full_name
    LEFT JOIN (
        SELECT u.full_name, COUNT(*) AS share_count
        FROM users u, shares sh
        WHERE u.id = sh.user_id
        AND sh.source = 'mobile'
        GROUP BY u.full_name) as shares_table
    ON likes_table.full_name = shares_table.full_name
    LEFT JOIN (
        SELECT u.full_name, COUNT(*) AS create_count
        FROM users u, create c
        WHERE u.id = c.user_id
        AND c.source = 'mobile'
        GROUP BY u.full_name) as create_table
    ON likes_table.full_name = create_table.full_name
ORDER BY TOTAL DESC