2013-05-10 61 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