2

我正在使用 ms sqlserver 2005。我有一个需要根据日期过滤的查询。假设我有一张包含电话号码和日期的表格。我需要在一个时间范围内(开始日期和结束日期)提供电话号码的计数。如果此电话号码出现在过去,则它们不应出现在结果计数中。我正在做这样的事情:

select (phoneNumber) from someTbl
where phoneNumber not in (select phoneNumber from someTbl where date<@startDate)

这对我来说看起来根本没有效率(并且它需要太多时间来执行导致一些可能应该在另一个问题中提出的副作用)我在 someTbl 中有大约 300K 行应该检查。

在我做这个检查之后,我需要再检查一件事。我有一个过去的数据库,其中包含另外 30K 的电话号码。所以我要添加

and phoneNumber not in (select pastPhoneNumber from somePastTbl)

这真的钉了棺材或压垮骆驼的最后一根稻草,或者你用来解释致命状态的任何短语。

所以我正在寻找一种更好的方法来执行这两个动作。


更新 我选择使用亚历山大的解决方案并最终得到这种查询:

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
                )

谢谢吉拉德

4

4 回答 4

2

因为它不只是将小于切换为大于。

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

更新

根据评论:

少于开始日期的月份

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
于 2013-05-01T09:55:47.517 回答
1

一个简单的索引

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;
于 2013-05-01T10:14:01.140 回答
1

另一种选择

SELECT t.phoneNumber
FROM SomeTbl t
WHERE t.date > @startDate
  AND NOT EXISTS (                          
                  SELECT 1
                  FROM SomePastTbl t2
                  WHERE t2.phoneNumber = t.phoneNumber                            
                  )
于 2013-05-01T13:25:05.610 回答
1

您需要最短开始日期大于开始日期的电话号码。这建议在进行计数(或创建列表)之前在电话号码级别进行聚合。

这是一种方法,带有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 
于 2013-05-01T13:39:37.220 回答