2016-02-29 117 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

很高兴帮助! –

相关问题