Reputation: 297
i'm using ms sqlserver 2005. i have a query that need to filter according to date. lets say i have a table containing phone numbers and dates. i need to provide a count number of phone numbers in a time frame (begin date and end date). this phone numbers shouldn't be in the result count if they appear in the past. i'm doing something like this :
select (phoneNumber) from someTbl
where phoneNumber not in (select phoneNumber from someTbl where date<@startDate)
This is looking not efficient at all to me (and it is taking too much time to preform resulting with some side effects that maybe should be presented in a different question) i have about 300K rows in someTbl that should be checked.
after i'm doing this check i need to check one more thing. i have a past database that contains yet another 30K of phone numbers. so i'm adding
and phoneNumber not in (select pastPhoneNumber from somePastTbl)
and that really nail the coffin or the last straw that break the camel or what ever phrase you are using to explain fatal state.
So i'm looking for a better way to preform this 2 actions.
UPDATE
i have choose to go with Alexander's solution and ended up with this kind of query :
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
)
Thanks Gilad
Upvotes: 2
Views: 166
Reputation: 4211
Since its a not in just switch the less than to a greater than.
select phoneNumber from someTbl where date > @startDate
Next to filter out 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
As Per comment:
Less than month of start date
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
Upvotes: 2
Reputation: 1269493
You want phone numbers whose minimum start date is greater than your start date. This suggests aggregation at the phone number level before doing the count (or creating the list).
Here is one way, with the condition in the having
clause:
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
You can also write this using window functions (SQL 2005 or greater). Here is a version using 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
Upvotes: 1
Reputation: 16894
One more option
SELECT t.phoneNumber
FROM SomeTbl t
WHERE t.date > @startDate
AND NOT EXISTS (
SELECT 1
FROM SomePastTbl t2
WHERE t2.phoneNumber = t.phoneNumber
)
Upvotes: 1
Reputation: 35696
one simple index
CREATE NONCLUSTERED INDEX IX_SomeTbl_date_phoneNumber
ON SomeTbl
(
date ASC,
phoneNumber ASC
)
then
SELECT phoneNumber FROM SomeTbl WHERE date > @startDate
EXCEPT
SELECT phoneNumber FROM SomePastTbl;
Upvotes: 1