我有一个具有以下结构的表:
Account_No Contact Date
-------------------------
1 2013-10-1
2 2013-9-12
3 2013-10-15
3 2013-8-1
3 2013-8-20
2 2013-10-25
4 2013-9-12
4 2013-10-2
我需要搜索该表并返回任何两个联系日期在30天之内的帐号。某些帐号可能有5或6个联系日期。我基本上只需要返回所有完整的帐号和彼此在30天内的记录,而忽略其余的。联系日期存储为日期数据类型。
因此,例如,帐号3将返回2013-8-1和2013-8-20记录,并且帐号4的两个记录也会出现,但不会显示其他帐号记录或帐户2013-10-15排名第3。
我使用的是SQL Server 2008 R2。
提前感谢您的帮助!
答案 0 :(得分:2)
您可以在+/- 30天内使用DATEADD并与时间窗口进行比较:
DECLARE @ContactDates TABLE (
Account_No int
, Contact Date
)
-- Sample data
INSERT @ContactDates (Account_No, Contact)
VALUES
(1, '2013-10-01')
, (2, '2013-09-12')
, (3, '2013-10-15')
, (3, '2013-08-01')
, (3, '2013-08-20')
, (2, '2013-10-25')
, (4, '2013-09-12')
, (4, '2013-10-02')
-- Find the records within +/-30 days
SELECT c1.Account_No, c1.Contact AS Contact_Date1
FROM @ContactDates AS c1
JOIN (
-- Inner query with the time window
SELECT Account_No
, Contact
, DATEADD(dd, 30, Contact) AS Date_Max
, DATEADD(dd, -30, Contact) AS Date_Min
FROM @ContactDates
) AS c2
-- Compare based on account number, exclude the same date
-- from comparing against itself. Usually this would be
-- a primary key, but this example doesn't show a PK.
ON (c1.Account_No = c2.Account_No AND c1.Contact != c2.Contact)
-- Compare against the +/-30 day window
WHERE c1.Contact BETWEEN c2.Date_Min AND c2.Date_Max
返回以下内容:
Account_No Contact
========== ==========
3 2013-08-20
3 2013-08-01
4 2013-10-02
4 2013-09-12
答案 1 :(得分:1)
在SQL Server 2012中,您将拥有lag()
和lead()
函数。在2008年,您可以对同一日历月中的值执行以下操作:
select distinct account_no
from t t1
where exists (select 1
from t t2
where t1.account_no = t2.account_no and
datediff(month, t1.ContactDate, t2.ContactDate) = 0
)
在定义日期在不同月份的“月份”时,存在一些挑战。 (2月15日之后,3月16日是“一个月”吗?他们的时间比1月1日和1月31日更近。)你可以选择30天:
select distinct account_no
from t t1
where exists (select 1
from t t2
where t1.account_no = t2.account_no and
datediff(day, t1.ContactDate, t2.ContactDate) <= 30
)
答案 2 :(得分:0)
每条记录都有一个ID吗?如果是这样你就不需要像我一样创建一个但基于你发布的数据
With cte as
(
Select *,
row_number() over (order by contact_date) id
From tbl
)
Select *
From cte b
Where exists (
Select 1
From cte a
Where a.account_no = b.account_no
And a.id <> b.id
And a.contact_date between b.contact_date and dateadd(d, 30, b.contact_date)
)