2011-09-22 57 views
2

我有一个两个表accountssubs
第一台具有id和第二表有场idrequester_account_idgrabber_account_id加入同一表两次在不同的密钥

我想要的帐户多少次请求做出的计数,和他(基于如果requester_account_id/grabber_account_id填充了多少抓斗他id

在一个查询

输出:

+------------+----------------+-----------------+ 
| account_id | subs_requested | subs_grabbed | 
+------------+----------------+-----------------+ 
| 1   | 4    | 3    | 
| 3   | 2    | 1    | 
+------------+----------------+-----------------+ 
+1

创建一个简洁的测试用例是为了_your_好处,而不是我们的。 –

+1

由于奶奶会说:“我不喜欢你的口气,先生” –

+0

@Tomalak,....。我没有发现这个问题有任何问题,它是明确的,可以清楚地回答。我不明白为什么我们需要测试用例。根本没有理由贬低这个问题! – TMS

回答

5

使用类似

select accounts.id, 
    count(distinct s1.id) as num_req, 
    count(distinct s2.id) as num_grab 
from accounts left join subs as s1 on accounts.id = s1.requester_account_id 
    left join subs as s2 accounts.id = s2.grabber_account_id 
group by accounts.id 

的技巧是使用表subs两次:subs as s1subs as s2,每一个不同的领域加入时间....

注:关于效率:我不知道,但我相信这个解决方案比子查询解决方案更快,但没有经过测试(至少它不会慢)。只要有可能,我总是更喜欢left join而不是子查询。

+0

这似乎是最干净的方式,但我会提醒说,我遇到过当MySQL中的聚合函数在左连接条件下的行为不如预期时。在投入生产之前确保您的结果合理。 –

+0

@Jeremy,感谢您的评论。你所说的潜在问题可能是左连接中NULL值的后果,但这对count()聚合函数不会造成问题。 – TMS

+0

感谢您的回复@TomasT。它是部分工作的 - 某些值在两列中均正确填充(当subs_requested或subs_grabbed为0时), 而其他似乎显示两列中subs_requested和subs_grabbed的* product *(如果两者均为非零) 。(如果subs_req = 6,subs_grabbed = 9,它在两列中都显示为54) 有什么想法? – Garfield

2

这应该工作:

SELECT a.account_id, 
(SELECT COUNT(*) FROM subs WHERE requester_account_id=a.account_id) AS subs_requested, 
(SELECT COUNT(*) FROM subs WHERE grabber_account_id=a.account_id) AS subs_grabbed 
FROM accounts a 
+0

我不知道这个解决方案是不是比我的答案中的2个左连接慢。尽可能使用子查询解决方案中的联接解决方案。 – TMS

+1

其实我认为你的解决方案不会给出预期的结果。与WHERE结合的COUNT(DISTINCT ...)应在所有行上给出0或1。我没有尝试过,但这就是我所期望的。至于SUBSELECTS的速度......取决于引擎和索引。但我认为这里没有提到速度问题。 – Frazz

+0

你是对的,谢谢! “独特”不应该在那里。我想要计算所有非空值。我纠正了我的解决方案 – TMS

0

你可以加入潜艇表只有一次,如果你想(不知道这个执行得更好)

select 
acc.id 
sum(if(sub.requester_account_id = acc.id, 1, 0)) as req, 
sum(if(sub.grabber_account_id = acc.id, 1, 0)) as grab 
from subs sub, accounts acc 
where sub.requester_account_id = acc.id or sub.grabber_account_id = acc.id 
group by acc.id 
+0

感谢您纠正我的文章! :-) – TMS

1

据我所知,你在找什么,它会是这样的:

select 
    a.id as account_id, 
    count(distinct sr.id) as requests, 
    count(distinct gr.id) as grabs 
from 
    accounts a 
left outer join subs sr 
    on sr.requester_account_id = a.id 
left outer join subs gr 
    on gr.grabber_account_id = a.id 

有时,我经历了奇怪的MySQL时做聚合f在左边的联合加入,所以这里是另一种方式:

select 
    a.id as account_id, 
    (select count(distinct sr.id) from subs sr where sr.requester_account_id = a.id) as requests, 
    (select count(distinct gr.id) from subs sr where gr.grabber_account_id = a.id) as grabs 
from 
    accounts a