MySQL使用UNION或OUTER LEFT JOIN

时间:2013-05-10 14:37:36

标签: php mysql

我一直在努力寻找一个简单的查询。 我有三个表,帐户,联系人和活动。 每次记录活动时,它都会记录AccountID,Contact Subject,TimeDate。

我查询“活动”表,向我显示每个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

等。

活动表有大约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;

根据我对UNION的理解,它应该返回一个唯一的列表(没有重复)。但我得到的是aprox 1400账户列表,当时我只有大约900个账户。

我尝试过LEFT OUTER JOIN,但这似乎永远存在(我在2小时后将其杀死)

有没有人对我可以尝试的内容有任何建议?

由于

2 个答案:

答案 0 :(得分: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子句中使用显式join语法(from关键字),而不是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;

答案 1 :(得分:0)

这取决于您是否要将选择与“或”或“和” - 逻辑组合。

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