【发布时间】:2019-12-06 11:13:22
【问题描述】:
我有一张包含联系人详细信息的表格:
表:tblContacts
CREATE TABLE tblContacts
(
Series INT,
ContacNumber INT,
CDate DATETIME
);
样本数据:
INSERT INTO tblContacts VALUES(12,123456,'2019-01-01');
INSERT INTO tblContacts VALUES(3,3456,'2019-01-01');
INSERT INTO tblContacts VALUES(12,123560,'2019-01-02');
INSERT INTO tblContacts VALUES(12,123459,'2019-01-05');
INSERT INTO tblContacts VALUES(3,3446,'2019-01-02');
INSERT INTO tblContacts VALUES(3,3486,'2019-01-03');
INSERT INTO tblContacts VALUES(3,34861,'2019-01-05');
INSERT INTO tblContacts VALUES(3,34862,'2019-01-07');
INSERT INTO tblContacts VALUES(12,127456,'2019-01-21');
INSERT INTO tblContacts VALUES(12,129456,'2019-02-03');
INSERT INTO tblContacts VALUES(12,126456,'2019-02-06');
INSERT INTO tblContacts VALUES(94,941256,'2019-01-01');
INSERT INTO tblContacts VALUES(94,944356,'2019-01-03');
INSERT INTO tblContacts VALUES(94,941356,'2019-01-07');
INSERT INTO tblContacts VALUES(94,943356,'2019-01-09');
我想找到那些在这些日期和通话前后 1 天或 2 天从未打电话的联系人。
注意:我可能会在通话前后折痕到任何级别,例如 1、2、3、4 等等。
预期输出:通话前后仅 1 天的以下输出。
ContacNumber CDate
----------------------------------------
3486 2019-01-03
NULL 2019-01-04
34861 2019-01-05
NULL 2019-01-06
34862 2019-01-07
123560 2019-01-02
NULL 2019-01-03 - 2019-01-04
123459 2019-01-05
NULL 2019-01-06 - 2019-01-20
127456 2019-01-21
NULL 2019-01-22 - 2019-02-02
129456 2019-02-03
NULL 2019-02-04 - 2019-02-05
126456 2019-02-06
941256 2019-01-01
NULL 2019-01-02
944356 2019-01-03
NULL 2019-01-04 - 2019-01-06
941356 2019-01-07
NULL 2019-01-08
943356 2019-01-09
我的尝试:以下查询仅适用于通话前后 1 天,但不适用于 1 天以外的时间。
查询:
; WITH Stage_1_CTE AS
(
SELECT Series,
ContacNumber,
CAST(CDate AS DATE) CDate,
ROW_NUMBER() OVER (PARTITION BY Series ORDER BY CAST(CDate AS DATE)) rnk1,
(ROW_NUMBER() OVER (PARTITION BY Series ORDER BY CAST(CDate AS DATE)))/2 rnk2,
(ROW_NUMBER() OVER (PARTITION BY Series ORDER BY CAST(CDate AS DATE)) + 1)/2 rnk3
FROM tblContacts
GROUP BY ContacNumber,CDate,Series
)
,
Stage_2_CTE AS
(
SELECT *,
CASE WHEN rnk1%2=1 THEN MAX(CASE WHEN rnk1%2=0 THEN CDate END) OVER (PARTITION BY Series,rnk2)
ELSE MAX(CASE WHEN rnk1%2=1 THEN CDate END) OVER (PARTITION BY Series,rnk3)
END AS CDate_Prev,
CASE WHEN rnk1%2=1 THEN MAX(CASE WHEN rnk1%2=0 THEN CDate END) OVER (PARTITION BY Series,rnk3)
ELSE MAX(CASE WHEN rnk1%2=1 THEN CDate END) OVER (PARTITION BY Series,rnk2)
END AS CDate_Next
FROM Stage_1_CTE
)
,Stage_Final_CTE AS
(
SELECT c.Series,
c.ContacNumber,
c.CDate,
EndDate = ''
FROM Stage_2_CTE c
WHERE c.CDate <> DATEADD(DAY, +1, CDate_Prev) OR c.CDate <> DATEADD(DAY, -1, CDate_Next)
UNION ALL
SELECT Series,
ContacNumber = NULL,
CDate = DATEADD(DAY, 1, c.CDate),
EndDate = ' - '+CAST(DATEADD(DAY, -1, CDate_Next) AS VARCHAR(10))
FROM Stage_2_CTE c
WHERE c.CDate <> DATEADD(DAY, -1, CDate_Next)
)
SELECT ContacNumber,
CASE WHEN CAST(CDate AS VARCHAR(10)) = REPLACE(EndDate,' - ','')
THEN CAST(CDate AS VARCHAR(10))
ELSE
CAST(CDate AS VARCHAR(10)) + CAST(EndDate AS VARCHAR(13))
END CDate
FROM Stage_Final_CTE
GROUP BY ContacNumber,CDate,EndDate,Series
ORDER BY Series,CDate;
【问题讨论】:
-
您可以尝试使用Minimal Reproducable Example 编辑问题吗?我正在努力理解这个问题。您是在询问如何在上面提供的数据中收集指定日期前后 2 天的数据?
-
“我想找到那些在这些日期和通话前后 1 天或 2 天从未打电话的联系人。”在什么日期?如果联系人在表中,那么大概他们在那个日期打电话。
-
@GordonLinoff,我的意思是说表格中缺少的那些日期,例如,我需要为每个系列生成开始日期和结束日期之间的所有日期,然后找出缺少的日期,如预期结果。
标签: sql sql-server sql-server-2008-r2