SQL查询选择优化
我正在使用ms sqlserver 2005.我有一个查询需要根据日期进行过滤。 可以说我有一个包含电话号码和日期的表格。 我需要提供时间范围内电话号码的计数(开始日期和结束日期)。 如果这些电话号码在过去出现,则不应将其计入结果计数。 我做这样的事情:SQL查询选择优化
select (phoneNumber) from someTbl
where phoneNumber not in (select phoneNumber from someTbl where date<@startDate)
这看起来效率不高,在所有我(和它花费过多时间瓶坯与一些副作用,也许应该在不同的问题,提交的结果) 我在某些TBL中有大约300K行,应该检查。
我做这个检查后,我需要检查一件事。 我有一个过去的数据库,其中包含另一个30K的电话号码。 所以我加入
and phoneNumber not in (select pastPhoneNumber from somePastTbl)
和真正钉棺材或打破骆驼或什么都使用的是解释致命状态短语的最后一根稻草。
所以我正在寻找更好的方法来预制这2个动作。
UPDATE 我已经选择去亚历山大的解决方案,结束了这种查询:
SELECT t.number
FROM tbl t
WHERE t.Date > @startDate
--this is a filter for different customers
AND t.userId in (
SELECT UserId
FROM Customer INNER JOIN UserToCustomer ON Customer.customerId = UserToCustomer.CustomerId
Where customerName = @customer
)
--this is the filter for past number
AND NOT EXISTS (
SELECT 1
FROM pastTbl t2
WHERE t2.Numbers = t.number
)
-- this is the filter for checking if the number appeared in the table before startdate
AND NOT EXISTS (
SELECT *
FROM tbl t3
WHERE t3.Date<@startDate and t.number=t3.number
)
感谢吉拉德
还有一个选项
SELECT t.phoneNumber
FROM SomeTbl t
WHERE t.date > @startDate
AND NOT EXISTS (
SELECT 1
FROM SomePastTbl t2
WHERE t2.phoneNumber = t.phoneNumber
)
嗨亚历山大,感谢您的简单解决方案。我采用了你的方法,在另一个需要完成的过滤中使用NOT EXISTS。我会接受你的答案,虽然它不完整,但它是真正的复制粘贴,以完成它与我需要的不同的过滤器。谢谢 – gilad 2013-05-01 14:20:07
没问题;)... – 2013-05-01 14:27:16
因为它是一个不只是开关小于一个大于。
select phoneNumber from someTbl where date > @startDate
下一页滤除somePastTbl
select s1.phoneNumber from someTbl s1
LEFT JOIN somePastTbl s2 on s1.phoneNumber = s2.phonenumber
where s1.date > @startDate and s2 IS NULL
UPDATE
按照评论:
于开始日期的月份少
SELECT COUNT(s1.phoneNumber) FROM someTbl s1
LEFT JOIN somePastTbl s2 on s1.phoneNumber = s2.phonenumber
where DATEADD(MONTH,-1,@startDate) < s1.date AND s1.date < @startDate and s2 IS NULL
嗨。以快速响应。我已经使用了关于旧数据的第二个陈述,它确实提高了性能。 – gilad 2013-05-01 10:49:13
嗨。以快速响应。我已经使用了关于旧数据的第二个陈述,它确实提高了性能。然而,第一个条件没有得到满足。我需要检查在请求的时间范围内出现的电话号码(可以在上个月说+12127773456)也不存在之前(如果我在+12127773456之前2个月也不应该计算它在当前的发生次数计数)。希望我让自己更清楚。感谢 – gilad 2013-05-01 10:55:05
@gilad所以如果我明白你需要知道它的存在时间不到一个月的开始日期? – AbstractChaos 2013-05-01 14:08:39
一个简单的索引
CREATE NONCLUSTERED INDEX IX_SomeTbl_date_phoneNumber
ON SomeTbl
(
date ASC,
phoneNumber ASC
)
然后
SELECT phoneNumber FROM SomeTbl WHERE date > @startDate
EXCEPT
SELECT phoneNumber FROM SomePastTbl;
你要电话号码,其最低开始日期比你的开始日期。这建议在进行计数(或创建列表)之前在电话号码级别进行聚合。
这里有一种方法,与having
子句中的条件:
select COUNT(*)
from (select t.phonenumber,
from someTble t left outer join
somePastTble pt
on t.phonenumber = pt.phonenumber
where pt.phonenumber is null
having MIN(date) >= @startdate
) t
你也可以这样写利用窗口函数(SQL 2005或更高版本)。下面是使用min()
版本:
select COUNT(distinct t.phonenumber)
from (select t.*, t.phonenumber, MIN(date) over (partition by phonenumber) as mindate
from someTble t
) t left outer join
somePastTble pt
on t.phonenumber = pt.phonenumber
where pt.phonenumber is null and mindate >= @startdate
嗨。感谢你的努力。在第一个选项中(我会坚持下去 - 在学习新东西的时候学习新东西足够了),没有考虑数字是否在@startdate之前在db中,然后它不应该被计数。 – gilad 2013-05-01 14:05:54
什么部分查询的花费最多时间的查询执行计划?索引是否提供?查询需要多长时间?什么是可接受的时间范围? – jpw 2013-05-01 09:56:01