SQL删除具有相同值的所有连续记录,只留下第一个和最后一个

时间:2014-11-26 04:47:51

标签: sql-server

我有一种情况,我需要删除共享相同字段值的连续记录(“无法通知客户”),但我需要保留第一个和最后一个实例

示例数据

date             type    log
20/11/2014 09:05 System, Order Added
20/11/2014 09:18 Mark,   Invoice Printed
20/11/2014 10:00 System, Failed to notify Customer
20/11/2014 10:05 System, Failed to notify Customer
20/11/2014 10:10 System, Failed to notify Customer
20/11/2014 10:15 System, Failed to notify Customer
20/11/2014 10:20 System, Failed to notify Customer
20/11/2014 12:05 System, Order Completed

结果输出

date             type    log
20/11/2014 09:05 System, Order Added
20/11/2014 09:18 Mark,   Invoice Printed
20/11/2014 10:00 System, Failed to notify Customer
20/11/2014 10:20 System, Failed to notify Customer
20/11/2014 12:05 System, Order Completed

有没有办法制定一个sql server查询来实现这个目的?对于我的生活,我无法理解我将如何接近这个

4 个答案:

答案 0 :(得分:4)

试试这个:

示例数据:

use tempdb

create table temp(
    [date]  datetime,
    type    varchar(100),
    [log]   varchar(100)
)
insert into temp values
('11/20/2014 09:05', 'System', 'Order Added'),
('11/20/2014 09:18', 'Mark', 'Invoice Printed'),
('11/20/2014 10:00', 'System', 'Failed to notify Customer'),
('11/20/2014 10:05', 'System', 'Failed to notify Customer'),
('11/20/2014 10:10', 'System', 'Failed to notify Customer'),
('11/20/2014 10:15', 'System', 'Failed to notify Customer'),
('11/20/2014 10:20', 'System', 'Failed to notify Customer'),
('11/20/2014 12:05', 'System', 'Order Completed');

使用ROW_NUMBER()的解决方案:

with cte as(
    select
        *,
        rn = row_number() over(partition by log order by [date]),
        cc = count(*) over(partition by log)
    from temp
    where
        log = 'Failed to notify Customer'
)
delete
from cte
where
    rn > 1 and rn < cc

select * from temp
drop table temp

答案 1 :(得分:3)

select * from table-name where  log='Failed to notify Customer' 
group by log having date>min(date) and date<max(date);

这将选择所需的行并删除这些行。

P.S - 语法可能有误,因为我没有执行和检查。

答案 2 :(得分:1)

选择包含每个客户和联合的最大(日期)的表,其中包含每个客户的最小值(日期)。然后从不在你的联盟中的表中删除。 像这样(未经测试)

DELETE FROM Table
WHERE NOT EXISTS
(SELECT Max(Date), Type, Log
FROM Table
WHERE type = 'System' AND log = 'Failed to notify customer'
GROUP BY Type, Log
UNION ALL
SELECT Min(Date), Type, Log
FROM Table
WHERE type = 'System' AND log = 'Failed to notify customer'
GROUP BY Type, Log)

答案 3 :(得分:1)

我们可以使用Group By和Having子句来获取计数大于1的日志值,然后我们可以得到相同的MIN和MAX日期。

检查此脚本:

--Create table
Create table #test
(
date1 datetime,
type varchar(25),
log1 varchar(100)
)

--Inserting data
Set dateformat dmy
Insert into #Test values(cast('20/11/2014 09:05' as datetime), 'System', 'Order Added')
Insert into #Test values(cast('20/11/2014 09:18' as datetime), 'Mark',   'Invoice Printed')
Insert into #Test values(cast('20/11/2014 10:00' as datetime), 'System', 'Failed to notify Customer')
Insert into #Test values(cast('20/11/2014 10:05' as datetime), 'System', 'Failed to notify Customer')
Insert into #Test values(cast('20/11/2014 10:10' as datetime), 'System', 'Failed to notify Customer')
Insert into #Test values(cast('20/11/2014 10:15' as datetime), 'System', 'Failed to notify Customer')
Insert into #Test values(cast('20/11/2014 10:20' as datetime), 'System', 'Failed to notify Customer')
Insert into #Test values(cast('20/11/2014 12:05' as datetime), 'System', 'Order Completed')

--Delete operation
Delete From #test 
Where date1 <> (Select MIN(date1) from #Test where log1 = ((SELECT Log1 from #test group by log1 having COUNT(log1) > 1)))
and date1 <> (Select MAX(date1) from #Test where log1 = ((SELECT Log1 from #test group by log1 having COUNT(log1) > 1)))
and log1 = (SELECT Log1 from #test group by log1 having COUNT(log1) > 1)

--Checking output
Select * from #Test