2013-05-10 124 views
0

我一直在努力寻找似乎足够简单的查询。 我有三个表,帐户,联系人&活动。 每次记录活动时,它都会记录AccountID,Contact Subject,TimeDate。MySQL使用UNION或OUTER LEFT JOIN

我查询“活动”表以显示每个AccountID上一周的所有活动计数。

我用:

select 
accounts.account as Account, 
count(distinct activities.contactid) as Users, 
from accounts, activities 
where activities.accountid=accounts.accountid 
AND completeddate >= curdate() - INTERVAL DAYOFWEEK(curdate())+6 DAY 
AND completeddate < curdate() - INTERVAL DAYOFWEEK(curdate())-1 DAY 
group by accounts.account asc; 

的结果是这样的:

Account  Users 
ACME Ltd  4 
Warner Bros 6 
RBS   9 

等。

活动表已baout 2000万行,这个运行在约20秒。

但是,我想要一个完整的列表。 我想将结果与尚未在该月进行任何活动的AccountID列表结合使用。

Account  Users 
ACME Ltd  4 
Warner Bros 6 
RBS   9 
Microsoft 0 or NULL 

等等

我试图UNION这样的:

select Account, '' from Accounts 
UNION 
select 
accounts.account as Account, 
count(distinct activities.contactid) as Users 
from accounts, activities 
where activities.accountid=accounts.accountid 
AND completeddate >= curdate() - INTERVAL DAYOFWEEK(curdate())+6 DAY 
AND completeddate < curdate() - INTERVAL DAYOFWEEK(curdate())-1 DAY 
group by accounts.account asc; 

从我了解关于联盟的是,它应该返回一个独特的名单(不重复)。但是,当我只有约900个账户时,我得到的是aprox 1400账户的列表。

我已经试过LEFT OUTER JOIN但这似乎只是一直运行下去(我杀了它后2小时)

有没有人有什么我可以尝试任何建议吗?

感谢

回答

1

难道这就是left outer join,你试过吗?

select accounts.account as Account, 
     count(distinct activities.contactid) as Users 
from accounts left outer join 
    activities 
    on activities.accountid=accounts.accountid 
where completeddate >= curdate() - INTERVAL DAYOFWEEK(curdate())+6 DAY and 
     completeddate < curdate() - INTERVAL DAYOFWEEK(curdate())-1 DAY 
group by accounts.account asc; 

这应该与原始查询具有大致相同的性能。

顺便说一句,你应该总是使用显式join语法(该from子句中join关键字),而不是一个隐含的加入where子句。

看来,completeddate是在活动表(总是使用别名)。这需要移动到在这种情况下,on条款:

select accounts.account as Account, 
     count(distinct activities.contactid) as Users 
from accounts left outer join 
    activities 
    on activities.accountid=accounts.accountid and 
     activities.completeddate >= curdate() - INTERVAL DAYOFWEEK(curdate())+6 DAY and 
     activities.completeddate < curdate() - INTERVAL DAYOFWEEK(curdate())-1 DAY 
group by accounts.account asc; 
+0

谢谢戈登,这就是我的尝试,但它只是给了我相同的结果:选择 accounts.account帐户, 计数(不同的活动。的ContactID),为用户从 帐户,活动 其中activities.accountid = accounts.accountid AND completeddate> = CURDATE() - INTERVAL DAYOFWEEK(CURDATE())+ 6 DAY AND completeddate user2054962 2013-05-10 14:58:16

+1

@ user2054962。 。 。您应该始终为您的列使用别名。 “completeddate”列在'activities'表(推测是)中,并且将'left outer join'转换为'inner join'。解决方案是将逻辑移入“on”子句。 – 2013-05-10 15:01:28

+0

谢谢戈登,现在只是测试它,我甚至不知道你冷用它那样!会让你知道它是怎么回事,谢谢。 – user2054962 2013-05-10 15:10:21

0

这取决于你是否希望将选择与“或”或“和”结合 - 逻辑。

对于“或”使用UNION DISTINCT表示“和”在主键上使用INNER JOIN

+0

我试过UNION DISTINCT,但由于某种原因,当我只有900个账户时,它给了我1495行。这是什么令我困惑。谢谢 – user2054962 2013-05-10 15:01:35

+0

如果您只选择帐户ID,它将起作用,否则它会认为结果不同,因为其他列是不同的。 – Adder 2013-05-10 15:13:26

+0

但后来我放弃了“计数”这是查询的总体目标。 – user2054962 2013-05-10 15:16:44