2014-01-15 56 views
0

我有一個SQL查詢,我需要......MYSQL找到那些沒有在n天

基本上我有兩個表我需要使用的幫助更新的日誌條目賬戶。一個包含客戶賬戶,另一個包含客戶服務代表與客戶交互的日誌。我想要這個查詢給我在過去14天內沒有日誌條目(交互)的任何帳戶的id。我也想過濾掉幾個不相關的代表賬戶(使用assignedto字段,你會看到)。另外,日誌表中的日期格式非常時髦,我不能改變它,因爲我沒有編寫的軟件也使用這個數據庫。

這兩個表格是cm.dbs (customer accounts)cm.log (interaction log)

這是我想出的查詢,但需要運行FOREVER。子查詢完美地工作並且只需要幾分之一秒,但是當主要查詢與子查詢一起運行時,它只是非常慢。我猜這是因爲子查詢正在爲主查詢中的每一行運行(並且不需要),但我對於如何解決這個問題毫無頭緒,因爲我不是SQL專家,我足夠了解創建基本到中間的查詢,這不是我以前做過的事情。

這裏是我創建至今的查詢:

SELECT id FROM cm.dbs WHERE id NOT IN (SELECT filenumber FROM cm.log 
    WHERE STR_TO_DATE(logdate, '%m/%d/%Y') 
    BETWEEN DATE_SUB(NOW(), INTERVAL 14 DAY) 
    AND NOW() 
    GROUP BY filenumber) 
    AND assignedto != 'OLD_ACCTS' 
    AND assignedto != 'HOUSE_ACCOUNTS' 
    AND assignedto != 'PAID_ACCOUNTS'; 

子查詢查找具有在過去兩週內,在日誌表項的賬戶。它完美地完成了這項工作。然後訣竅就是讓主查詢找到所有沒有條目的賬戶。

另請注意,cm.log中的filenumber字段對應於cm.dbs表中的id

我可能以一種完全愚蠢的方式來解決這個問題,我不是在承認這一點。任何有關使這項工作正確和有效的投入是讚賞。我也喜歡任何人推薦解釋的修復/更改。我不是簡單地想要爲我建立的查詢,我想了解我做錯了什麼,以及如何更好地做到這一點,所以下次我可以自己弄清楚。我很少問過這樣的問題,我通常會自己弄清楚這些問題,但這讓我很難過。

編輯:這裏是表中的相關領域的部分架構:

cm.dbs:

id int(10) UN PK AI 

title varchar(45) 

firstname varchar(200) 

middlename varchar(200) 

lastname varchar(200) 

fullname varchar(200) 

address varchar(200) 

address2 varchar(200) 

city varchar(200) 

state varchar(200) 

zip varchar(50) 

assignedto varchar(200) 

... 

cm.log:

id int(10) UN PK AI 

filenumber varchar(200) 

agentname varchar(200) 

logtime varchar(200) 

logdateandtime varchar(200) 

logdate varchar(200) 

logmessage mediumtext 
+0

您能否提供涉及查詢的兩個表的模式。兩張桌子都有多少記錄? – Rahul

+0

cm.dbs表字面上有超過100個字段,所以我不確定是否發佈了所有有效的產品,但是如果您覺得有必要,我會這樣做。如果你想知道什麼樣的索引,鑰匙等,那裏沒有。這是由第三方創建的數據庫,它確實寫得很差。多麼糟糕?那麼,那個時髦的日期字段?這是一個VARCHAR(200)。爲什麼!!!?? –

+1

一個優化就是將'logdate'字段轉換爲本地類型 - 您迫使mysql將該字符串轉換爲表中每條記錄的日期值。這可以防止使用索引並強制每次都進行全表掃描。 –

回答

0

這是最好的我可以在沒有數據庫模式的情況下執行,但希望與您正在尋找的內容非常接近(或者至少指向正確的方向):

SELECT DISTINCT dbs.id 
FROM cm.dbs, cm.log 
WHERE dbs.id = log.filenumber 
     AND STR_TO_DATE(log.logdate, '%m/%d/%Y') NOT BETWEEN DATE_SUB(NOW(), INTERVAL 14 DAY) AND NOW() 
     AND dbs.assignedto NOT IN ('OLD_ACCTS','HOUSE_ACCOUNTS','PAID_ACCOUNTS'); 

如果您有機會在您的查詢中運行EXPLAIN並將輸出添加到您的問題中,那麼我們可以更好地配置它(幷包括數據庫模式)。

+0

我剛剛做了,它花了0.8秒運行。現在看數據,看看它是否正確。 (並不是我懷疑你:) –

+0

此查詢獲取2周內的記錄,而不是最近2周內沒有記錄的記錄。 –

+0

你是對的,我在重構查詢時錯過了。現在修復(希望)。 – user1853181

0

你的查詢看起來正確的我,除了下面的變化(因爲你有,使用IN運營商,而不是讓他們在不同的OR專門進行檢查多個assignedto值。)

SELECT id FROM cm.dbs WHERE id NOT IN (SELECT filenumber FROM cm.log 
    WHERE STR_TO_DATE(logdate, '%m/%d/%Y') 
    BETWEEN DATE_SUB(NOW(), INTERVAL 14 DAY) 
    AND NOW() 
    GROUP BY filenumber) 
    AND assignedto NOT IN ('OLD_ACCTS','HOUSE_ACCOUNTS','PAID_ACCOUNTS'); 
+0

對帳號使用NOT IN有完整意義。謝謝。 –

0

我認爲你是以錯誤的方式攻擊它。讓我們分解你正在尋找的東西。

第一件事是filenumber和最大LOGDATE:

SELECT filenumber, MAX(logdate) 
FROM cm.log 
GROUP BY filenumber 

所以現在我們只是需要把它加入到另一個表:

SELECT filenumber, MAX(logdate), assignedto 
FROM cm.log as log 
INNER JOIN cm.dbs as dbs ON log.filenumber = dbs.id 
GROUP BY filenumber 

現在,我們要應用在我們的一些條件剛剛選擇(2周以前,不在這3組中):

SELECT * FROM (
    SELECT log.filenumber, MAX(logdate) as logdate, assignedto 
    FROM cm.log as log 
    INNER JOIN cm.dbs as dbs ON log.filenumber = dbs.id 
    GROUP BY filenumber) t 
WHERE logdate < DATE_SUB(NOW(), INTERVAL 14 DAY) 
AND assignedto NOT IN ('OLD_ACCTS','HOUSE_ACCOUNTS','PAID_ACCOUNTS') 
+0

我試着在MYSQL Workbench中運行這個,並且得到了一個查詢中斷的錯誤。不知道爲什麼,我想弄明白。 –

+0

我能夠通過修改它來運行它,但它與我認爲工作的其他查詢有同樣的問題;它不會清除具有比14天更新和更新的日誌條目的文件編號。如果某個帳戶的某個條目超過14天,且該條目較新,則會包含該條目。這是行不通的。 –

+0

上述代碼應只返回MAX(最近的)logdate早於14天的文件編號。 –

相關問題