2013-02-27 37 views
0

用户表:选择多个计数时表不能直接共涉及

  • USER_ID(不同对每个用户)
  • SOURCE_ID(用户可能具有相同的源)

统治表:

  • white_rules
  • black_rules
  • general_rules
这些

表看起来都一样,并具有:

  • victim_id(助涉及从用户表中user_id说明)。
  • RULE_ID(共同涉及一种不同的表,该表不在这里重要)

什么我需要的是,以提取的每SOURCE_ID总规则每型(白色,黑色,一般)的量。

例如:

  • SOURCE_ID:5 --->总70个白色规则,总共32条黑规则,共有21条一般规则
  • SOURCE_ID:7 --->总2条白色规则,总0黑规则,总共4条一般规则

等等......对于在用户表上列出的所有不同来源。

我的尝试是:

SELECT source_id, 
count(w.victim_id) as total_white, 
count(b.victim_id) as total_black, 
count(g.victim_id) as total_general 
from users 
LEFT JOIN white_rules as w ON (user_id=w.victim_id) 
LEFT JOIN black_rules as b ON (user_id=b.victim_id) 
LEFT JOIN general_rules as g ON (user_id=g.victim_id) 
where deleted='f' and source is not null 
group by source; 

但结果表中,我得到了错误的(高)的数字比我期望得到, 所以我必须做一些错误:) 希望任何铰链在正确的方向。

+0

什么是在'WHERE'和'GROUP BY'使用'source'? – 2013-02-27 17:18:12

回答

0

您需要在子查询中进行计数,或者计数不同,因为您的多个1对多关系导致交叉连接。我不知道您的数据,但想象一下这样的场景:

用户:

User_ID | Source_ID 
--------+-------------- 
    1  |  1 

White_Rules

Victim_ID | Rule_ID 
----------+------------- 
    1  | 1 
    1  | 2 

Black_Rules

Victim_ID | Rule_ID 
----------+------------- 
    1  | 3 
    1  | 4 

如果运行

SELECT Users.User_ID, 
     Users.Source_ID, 
     White_Rules.Rule_ID AS WhiteRuleID, 
     Black_Rules.Rule_ID AS BlackRuleID 
FROM Users 
     LEFT JOIN White_Rules 
      ON White_Rules.Victim_ID = Users.User_ID 
     LEFT JOIN Black_Rules 
      ON Black_Rules.Victim_ID = Users.User_ID 

您将获得White_Rules.Rule_IDBlack_Rules.Rule_ID所有组合:

User_ID | Source_ID | WhiteRuleID | BlackRuleID 
--------+-----------+-------------+------------- 
    1  | 1  |  1  |  3 
    1  | 1  |  2  |  4 
    1  | 1  |  1  |  3 
    1  | 1  |  2  |  4 

所以计算的结果将返回4分白色的规则和4条黑色的规则,即使只有2每。

你应该得到所需要的结果,如果你改变你的查询到这一点:

SELECT Users.Source_ID, 
     SUM(COALESCE(w.TotalWhite, 0)) AS TotalWhite, 
     SUM(COALESCE(b.TotalBlack, 0)) AS TotalBlack, 
     SUM(COALESCE(g.TotalGeneral, 0)) AS TotalGeneral 
FROM Users 
     LEFT JOIN 
     ( SELECT Victim_ID, COUNT(*) AS TotalWhite 
      FROM White_Rules 
      GROUP BY Victim_ID 
     ) w 
      ON w.Victim_ID = Users.User_ID 
     LEFT JOIN 
     ( SELECT Victim_ID, COUNT(*) AS TotalBlack 
      FROM Black_Rules 
      GROUP BY Victim_ID 
     ) b 
      ON b.Victim_ID = Users.User_ID 
     LEFT JOIN 
     ( SELECT Victim_ID, COUNT(*) AS TotalGeneral 
      FROM General_Rules 
      GROUP BY Victim_ID 
     ) g 
      ON g.Victim_ID = Users.User_ID 
WHERE Deleted = 'f' 
AND  Source IS NOT NULL 
GROUP BY Users.Source_ID 

Example on SQL Fiddle

另一种方法是:

SELECT Users.Source_ID, 
     COUNT(Rules.TotalWhite) AS TotalWhite, 
     COUNT(Rules.TotalBlack) AS TotalBlack, 
     COUNT(Rules.TotalGeneral) AS TotalGeneral 
FROM Users 
     LEFT JOIN 
     ( SELECT Victim_ID, 1 AS TotalWhite, NULL AS TotalBlack, NULL AS TotalGeneral 
      FROM White_Rules 
      UNION ALL 
      SELECT Victim_ID, NULL AS TotalWhite, 1 AS TotalBlack, NULL AS TotalGeneral 
      FROM Black_Rules 
      UNION ALL 
      SELECT Victim_ID, NULL AS TotalWhite, NULL AS TotalBlack, 1 AS TotalGeneral 
      FROM General_Rules 
     ) Rules 
      ON Rules.Victim_ID = Users.User_ID 
WHERE Deleted = 'f' 
AND  Source IS NOT NULL 
GROUP BY Users.Source_ID 

Example on SQL Fiddle

+0

非常感谢你! – ktopaz 2013-03-03 09:05:55