我有一个数据集,需要选择并保留没有重叠时间范围的记录,而对于那些有重叠时间的记录,则保留最早的记录。
我已经能够使用以下代码成功选择没有重叠时间范围的记录:
IF OBJECT_ID('tempdb..#overlaps') IS NOT NULL DROP Table #overlaps
SELECT
CASE WHEN EXISTS(SELECT 1 FROM #service r2
WHERE r2.client_ID = r1.client_ID
AND r2.service_ID <> r1.service_ID
AND r1.service_start_date <= r2.service_end_date
AND r2.service_start_date <= r1.service_end_date)
THEN 1
ELSE 0
END AS Overlap
,*
into #overlaps
FROM #services r1
这将生成以下示例客户端:
Overlap client_ID service_ID service_start_date service_end_date
1 12345 123 27-Oct-2009 03-Jan-2013
1 12345 124 27-Dec-2012 19-Mar-2013
1 12345 125 18-Mar-2013 04-Jun-2014
1 12345 126 29-Jun-2014 28-Apr-2017
1 12345 127 23-Jun-2014 14-Aug-2014
1 12345 128 27-Apr-2015 07-Nov-2015
1 12345 129 01-Aug-2015 01-Dec-2015
0 12345 132 01-Jul-2017 09-Dec-2017
0 12345 133 02-Jan-2018 20-Jan-2018
0 12345 134 03-May-2018 05-Jun-2018
我想做的是在重叠= 1的情况下,如果该记录是重叠“集合”的第一条记录,则在标记上添加一列,就开始日期而言是第一条。 service_ID实际上不是顺序的,我只是将其替换为虚拟数据。
因此,在上述情况下,记录#1应标记为1,因为与重叠的服务记录#2相比,记录#1具有最早的服务开始,因此记录#2将标记为0,相同记录#3(即标记为0)。继续,记录#4应该标记为1,因为它与下面的记录重叠。
关于最终产品,我最终只想显示任何不重叠的期间,以及确实重叠的记录的最早/第一条记录,因此在上述情况下,记录#1、4、8、9,剩下的10个将被删除。不过,每条记录都应保留为自己的记录,不应将其“透视”为连续的记录。
换句话说,我需要标记的是最早的记录,该记录开始于并行发生多个活动服务的地方。
编辑:
例如,客户有4个服务:服务A从1月1日开始-7月31日,服务B从2月1日开始的8月1日结束,服务C从9月1日开始的10月1日结束,服务D从11月1日开始的12月1日结束...服务A应该标记为1,将在服务A仍处于活动状态时启动的服务B标记为0,将在没有任何服务处于活动状态的情况下启动服务C的标记为1,与服务D相同。
答案 0 :(得分:0)
我认为标记是:
SELECT (CASE WHEN NOT EXISTS (SELECT 1
FROM #service r2
WHERE r2.client_ID = r1.client_ID AND
r2.service_ID <> r1.service_ID AND
r1.service_start_date <= r2.service_end_date AND
r2.service_start_date < r1.service_end_date
)
THEN 1
ELSE 0
END) AS First_Overlap;
注意:
overlaps
标志进行检查,也可以包含exists
查询。<
与<=
。此外,我怀疑您正在尝试解决差距与岛屿的问题。不需要使用多个临时表,也不需要使用所使用的逻辑。您可能要问有关您要解决的整个问题的另一个问题,而不是这个方面。
答案 1 :(得分:0)
UPDATE #overlaps SET IsFirst=1
FROM
(SELECT overlap, client_id client_id, service_start_date service_start_date, service_end_date service_end_date, min(service_id) service_id
FROM #overlaps
WHERE overlap=1
group by overlap, client_id, service_start_date, service_end_date) a
where #overlaps.client_id = a.client_id and #overlaps.service_id = a.service_id
@ marshymell0-我想我正在理解你想要的。将其写为查询非常棘手,所以我改用游标。在我有PRINT @service_start_date_prev
行的部分中,您将更新标志列,该标志列确定记录是否是重叠集中的第一条记录。
DECLARE @overlap_prev int, @client_id_prev int, @service_id_prev int
DECLARE @overlap_next int, @client_id_next int, @service_id_next int
DECLARE @service_start_date_prev datetime, @service_end_date_prev datetime
DECLARE @service_start_date_next datetime, @service_end_date_next datetime
DECLARE @part_of_set int = 0
DECLARE o_cursor CURSOR
FOR SELECT overlap, client_id, service_id, service_start_date, service_end_date
FROM #overlaps where overlap=1
ORDER BY service_start_date
OPEN o_cursor
FETCH NEXT FROM o_cursor
INTO @overlap_next, @client_id_next, @service_id_next, @service_start_date_next, @service_end_date_next
WHILE @@FETCH_STATUS = 0
BEGIN
IF (@service_start_date_prev IS NOT NULL)
BEGIN
IF (@part_of_set = 0 AND @service_start_date_prev <= @service_end_date_next AND @service_start_date_next <= @service_end_date_prev)
BEGIN
PRINT @service_start_date_prev
SET @part_of_set = 1
END
ELSE
SET @part_of_set = 0
END
SET @overlap_prev = @overlap_next
SET @client_id_prev = @client_id_next
SET @service_id_prev = @service_id_next
SET @service_start_date_prev = @service_start_date_next
SET @service_end_date_prev = @service_end_date_next
FETCH NEXT FROM o_cursor
INTO @overlap_next, @client_id_next, @service_id_next, @service_start_date_next, @service_end_date_next
END
CLOSE o_cursor;
DEALLOCATE o_cursor;
答案 2 :(得分:0)
很难在此处阅读确切的目标,但是如果您希望基于service_start_date
进行标记,则Overlap
= 1即可。
;WITH CTE (Overlap, client_ID, service_ID, service_start_date) AS (
SELECT * FROM (
VALUES
('1','12345','123','10/27/2009'),
('1','12345','124','12/27/2012'),
('1','12345','125','3/18/2013'),
('1','12345','126','6/29/2014'),
('1','12345','127','6/23/2014'),
('1','12345','128','4/27/2015'),
('1','12345','129','8/1/2015'),
('0','12345','132','7/1/2017'),
('0','12345','133','1/2/2018'),
('0','12345','134','5/3/2018')
) AS A (Overlap, client_ID, service_ID, service_start_date)
)
SELECT CTE.Overlap,
CTE.client_ID,
CTE.service_ID,
CTE.service_start_date,
t2.Result
FROM CTE
LEFT JOIN (
SELECT '1' AS Result,
t2.client_ID,
MIN(t2.service_start_date) AS service_start_date
FROM CTE t2
WHERE t2.Overlap = '1'
GROUP BY client_ID
) t2 ON CTE.client_ID = t2.client_ID
AND CTE.service_start_date = t2.service_start_date
ORDER BY service_ID
除了用Overlap
标记第一个service_start_date
之外,这还不算什么。例如,如果您想将那些不是第一个标记为0的标记,则需要添加。