2016-02-29 115 views
0

我有一個包含Customers,Subscriptions和Publications表的訂閱數據庫。從SQL查詢中排除可能結果的最有效方法是什麼?

訂閱表包含所有訂閱記錄,每個記錄有三個標誌來標記狀態:isActive,isExpire和isPending。這些是布爾值,只有一個標誌可以爲真 - 這是由應用程序處理的。

我需要確定所有未更新他們之前訂閱的雜誌的客戶,而且我不確定自己是否編寫了最有效的SQL查詢。如果我發現已經失效的訂閱,那麼如果他們已經擁有該特定雜誌的活動訂閱或待定訂閱,我需要忽略它。

這是我有:

SELECT DISTINCT Customers.id, Subscriptions.publicationName 
FROM Subscriptions 
LEFT JOIN Customers 
ON Subscriptions.id_Customer = Customers.id 
LEFT JOIN Publications 
ON Subscriptions.id_Publication = Publications.id 
WHERE Subscriptions.isExpired = 1 
AND NOT EXISTS 
(SELECT * FROM Subscriptions s2 
WHERE s2.id_Publication = Subscriptions.id_Publication 
AND s2.id_Customer = Subscriptions.id_Customer 
AND s2.isPending = 1) 
AND NOT EXISTS 
(SELECT * FROM Subscriptions s3 
WHERE s3.id_Publication = Subscriptions.id_Publication 
AND s3.id_Customer = Subscriptions.id_Customer 
AND s3.isActive = 1) 

我剛剛超過50,000訂閱記錄,此查詢需要近一個小時運行,它告訴我,有很多循環或一些事情,其中​​的每條記錄的SQL引擎必須再次搜索才能找到任何'isPending'和'isActive'記錄。

這是我的第一篇文章,所以請溫柔,如果我錯過了我的問題中的任何信息:)謝謝。

+0

它正在運行什麼硬件? –

+0

在你的數據庫中,我認爲訂閱表中的每一行都是'訂閱'的'續訂'是否正確?我的意思是假設客戶擁有一本雜誌,並且子分期到2015年12月。當他續訂訂閱時,它是否在訂閱表中創建了新行,還是僅僅將狀態轉回到活動狀態? –

+0

Windows Server 2012 R2 Essentials 64位 Intel Xeon CPU E3-1220 v3 @ 3.10Ghz 4Gb RAM –

回答

0

我沒有完整的數據庫結構,因此我無法測試以下查詢,但它可能包含一些優化。我會留給你測試,但會解釋爲什麼我改變了,我改變了。

select Distinct Customers.id, Subscriptions.publicationName 
from Subscriptions 
join Customers on Subscriptions.id_Customer = Customer.id 
join Publications 
ON Subscriptions.id_Publication = Publications.id 
Where Subscriptions.isExpired = 1 
And Not Exists 
(select * from Subscriptions s2 
join Customers on s2.id_Customer = Customer.id 
join Publications 
ON s2.id_Publication = Publications.id 
where s2.id_Customer = s2.id_customer and 
(s2.isPending = 1 or s2.isActive = 1)) 

如果您在客戶或出版物DB沒有得到的數據,則認購事項的信息是沒有用的,所以我消除了LEFT贊成加入的單純加入。組合兩個Exists子查詢。如果我回憶起來,這些都非常密集,越少越好。最後一件我沒有在上面列出但可能值得研究的東西是,你可以運行一個帶有特定數據字段的子查詢並將它用在Exists子句中嗎?使用Select *將返回所有減慢處理速度的數據字段。我不確定你是否可以不幸地限制你的結果,因爲我沒有一個可用於我的等效DB,我可以測試(谷歌可能知道)。

我懷疑可以對此查詢進行進一步的優化。刪除Exists子句以支持'IN'子句可能會有所幫助,但我現在無法想出一種方法,看看您如何匹配兩個唯一字段(客戶ID和相關訂閱)。讓我知道這是否有幫助。

對於50k行的表格,您應該可以在幾秒鐘內運行這樣的查詢。

+0

非常感謝。使用'OR'來結合'isPending = 1'和'isActive = 1'已經有了真正的改進。我感謝你的幫助:) –

+0

很高興幫助! –

相關問題