Reputation: 101
This is my table records
field_date field_time field_id
20161202 12:56:00 309073
20161202 12:57:00 208901
20161202 12:58:00 208901
20161202 13:15:00 208901
with the same id there (208901) I want to delete the ID with time interval below 15 minutes, for example there, this is the result I want
field_date field_time field_id
20161202 12:56:00 309073
20161202 12:57:00 208901
20161202 13:15:00 208901
id with 12:58:00 time was deleted because it has only 1 minute interval with the id first record, but the 13:15:00 not deleted because the interval is more than 15 minutes from the first record.
Here is my code, it still show the 12:58:00 records and I want to delete it so I'm going to only show the record with less than 15 minutes interval, this code just show all records (not the duplicate record that i want), what's wrong there?
SELECT *
FROM tbl_name WHERE EXISTS (SELECT 1 FROM tbl_name t2
WHERE(t2.field_id = tbl_name.field_id AND
DATEDIFF(MINUTE, t2.field_time, tbl_name.field_time) <= 15)
)
ORDER BY field_time
Upvotes: 2
Views: 77
Reputation: 5094
Try this,
DECLARE @DataSource TABLE
(
[field_date] INT
,[field_time] VARCHAR(8)
,[field_id] INT
);
INSERT INTO @DataSource ([field_date], [field_time], [field_id])
VALUES (20161202, '12:56:00', 309073 )
,(20161202, '12:57:00', 208901)
,(20161202, '12:58:00', 208901)
,(20161202, '13:15:00', 208901);
;with CTE as
(
select *,ROW_NUMBER()over(PARTITION by [field_date], [field_id] ORDER BY [field_time] ASC)rn from @DataSource A
)
, CTE1 as
(
select *,1 flg from cte where rn=1
UNION ALL
select c.*,case when (DATEDIFF(MINUTE, c1.field_time,c.field_time) <= 15) then 0 else 1 end from cte c
inner join cte1 c1 on c1.[field_id]=c.[field_id]
where c.rn=c1.rn+1
)
select * from cte1
where flg=1
order by [field_id],field_time
Upvotes: 0
Reputation: 43646
What about this (for SQL Server 2012+):
DECLARE @DataSource TABLE
(
[field_date] INT
,[field_time] VARCHAR(8)
,[field_id] INT
);
INSERT INTO @DataSource ([field_date], [field_time], [field_id])
VALUES (20161202, '12:56:00', 309073 )
,(20161202, '12:57:00', 208901)
,(20161202, '12:58:00', 208901)
,(20161202, '13:15:00', 208901);
WITH DataSource ([field_date], [field_time], [field_id], [timeDiff]) AS
(
SELECT *
,DATEDIFF(MINUTE, MIN([field_time]) OVER(PARTITION BY [field_date], [field_id] ORDER BY [field_time] ASC), [field_time])
FROM @DataSource
)
SELECT *
FROM DataSource
WHERE [timeDiff] = 0
OR [timeDiff] > 15
ORDER BY field_time;
Upvotes: 1
Reputation: 1815
Try as follows:
DECLARE @DATEDIFF TABLE (ID INT IDENTITY(1,1),FIELD_DATE DATE,FIELD_TIME TIME,FIELD_ID INT)
INSERT INTO @DATEDIFF SELECT * FROM TABLE1
DECLARE @FIELD_ID INT,@FIELD_DATE DATE,@FIELD_TIME TIME,@ID INT,@NEXT_TIME TIME,@NEXT_DATE DATE
DECLARE C CURSOR FOR
SELECT DISTINCT FIELD_ID FROM @DATEDIFF
OPEN C
FETCH NEXT FROM C INTO @FIELD_ID
WHILE @@FETCH_STATUS=0
BEGIN
DECLARE D CURSOR FOR
SELECT ID,FIELD_DATE ,FIELD_TIME FROM @DATEDIFF WHERE FIELD_ID = @FIELD_ID
OPEN D
FETCH NEXT FROM D INTO @ID,@FIELD_DATE,@FIELD_TIME
WHILE @@FETCH_STATUS=0
BEGIN
SET @NEXT_TIME=(SELECT FIELD_TIME FROM @DATEDIFF WHERE ID=@ID+1 AND FIELD_ID = @FIELD_ID )
SET @NEXT_DATE=(SELECT FIELD_DATE FROM @DATEDIFF WHERE ID=@ID+1 AND FIELD_ID = @FIELD_ID )
IF EXISTS(SELECT FIELD_TIME FROM @DATEDIFF WHERE ID=@ID+1 AND FIELD_ID = @FIELD_ID)
BEGIN
IF ( DATEDIFF (MI,CAST(@FIELD_DATE AS VARCHAR(100))+' '+CAST(@FIELD_TIME AS VARCHAR(100)),CAST(@NEXT_DATE AS VARCHAR(100))+' '+CAST(@NEXT_TIME AS VARCHAR(100))))<15
DELETE FROM @DATEDIFF WHERE ID=@ID+1 AND FIELD_ID = @FIELD_ID
END
FETCH NEXT FROM D INTO @ID,@FIELD_DATE,@FIELD_TIME
END
CLOSE D
DEALLOCATE D
FETCH NEXT FROM C INTO @FIELD_ID
END
CLOSE C
DEALLOCATE C
SELECT * FROM @DATEDIFF
Upvotes: 0
Reputation: 5743
DECLARE @Data TABLE ([field_date] int, [field_time] varchar(8), [field_id] int);
INSERT INTO @Data
VALUES
(20161202, '12:56:00', 309073),
(20161202, '12:57:00', 208901),
(20161202, '12:58:00', 208901),
(20161202, '13:15:00', 208901)
;
;WITH data AS
(
SELECT
*,
-- A field easier to use for comparison, e.g. cross date
CONVERT(datetime, CAST(field_date AS char(8)), 112) + CONVERT(time, field_time) AS combined_time
FROM @Data
)
DELETE curr
FROM
data curr
OUTER APPLY
(
SELECT TOP 1 *
FROM data prev
WHERE
prev.field_id = curr.field_id
-- assume the record does not contain duplicate record of field_time
AND prev.combined_time < curr.combined_time
ORDER BY combined_time DESC
) AS prev
WHERE DATEDIFF(MINUTE, prev.combined_time, curr.combined_time) <= 15
-- Result
SELECT * FROM @Data
Upvotes: 0