【问题标题】:merge ALMOST duplicate records IN sql在sql中合并几乎重复的记录
【发布时间】:2012-01-20 15:34:20
【问题描述】:

大家好……

我有两个表,它们的结构是相同的......

表日志详情

Date              Time         CardID        Status  
2012-01-20        00:00:00     A1            ABSENT
2012-01-20        00:00:00     B1            ABSENT
2012-01-20        00:00:00     C3            ABSENT
2012-01-20        00:00:00     D1            ABSENT

表preStatus

Date            Time        CardID        Status
2012-01-20     07:00:10     A1            COMING
2012-01-20     07:10:00     C3            COMING
2012-01-20     08:00:00     B1            LATE
2012-01-20     17:00:00     B1            BACK
2012-01-20     17:10:10     A1            BACK
2012-01-20     17:13:00     C3            BACK

合并后

Date
2012-01-20     07:00:10     A1            COMING
2012-01-20     07:10:00     C3            COMING
2012-01-20     08:00:00     B1            LATE
2012-01-20     00:00:00     D1            ABSENT
2012-01-20     17:00:00     B1            BACK
2012-01-20     17:10:10     A1            BACK
2012-01-20     17:13:00     C3            BACK

我如何合并这两个表,因为在表 b 中有重复的记录,当我这样做时 合并...

merge into logDetail as Target 
using preStatus as Source
on Target.L_Date=Source.L_Date
and Target.L_Time='00:00:00'
and Target.L_CardID=Source.L_CardID 
when matched then

update set Target.L_Status=Source.L_Status,
Target.L_Time=Source.L_Time
when not matched then
insert (L_Date,L_Time,L_CardID,L_Status) 
                           values(Source.L_Date,Source.L_Time,Source.L_CardID,Source.L_Status);

它说 MERGE 语句多次尝试更新或删除同一行

非常感谢任何帮助。

【问题讨论】:

  • c# 标签似乎与此处无关。

标签: sql-server merge


【解决方案1】:

您似乎不想合并表,因为 CardID 不是主键。

您似乎希望保留 Status = "COMING" 的条目,即使有新条目 stats = "BACK"。

我建议您分两步执行此操作,首先插入 preStatus 数据,然后删除存在“COMING”和“BACK”行的“ABSENT”行。

/* Insert new data */
insert logDetail
select * from preStatus

/* Delete Absent rows where there is a COMING or BACK row for the same item on the same day */
Delete logDetail
from logDetail ld1
where 
    /* Absent rows only */
    ld1.time = '00:00:00'
and ld1.Status = 'ABSENT'
/*  And there must be a COMING or BACK row for the same card on the same day */
and exists (
   select 1 from logDetail ld2
   where ld2.Date = ld1.Date
   and ld2.CardID = ld1.CardID
   and ld2.Time > '00:00:00'
   and ld2.Status <> 'ABSENT'
)

要删除具有相同日期、卡 ID 和相同状态但有更晚时间的行:

Delete logDetail
from logDetail ld1
where 
ld1.status in ('COMING', 'BACK')
/*  COMING or BACK row only */ 
      /* for the same card on the same day, with a later time*/
and exists (
   select 1 from logDetail ld2
   where ld2.Date = ld1.Date      
   and ld2.CardID = ld1.CardID
   and ld2.Status = ld1.Status
   and ld2.Time > ld1.Time
)

【讨论】:

  • 这两个步骤可能应该作为一个事务完成,以纠正MERGE原子性的损失。
  • 第二步是幂等的,即可以重复而不改变结果,如果第一步失败也没有效果。
  • 感谢 Ben 和大家......它就像魅力一样!但我还有另一个要问...如果我想删除几乎重复的记录,该怎么做...例如我有两条记录,但仅在列时间不同..我只想保留最旧的记录记录并删除其他...人怎么样?
  • @ApizZest,查看修改后的答案。
  • 再次感谢本...这对我很有帮助!我在这里有一个主题之外的问题类型...如果我从 mssql 更改或迁移到 mysql,这些所有查询仍然有效吗?
【解决方案2】:

匹配时不做任何事情,这应该解决吗?

【讨论】:

  • 我对这句话有问题“MERGE 语句试图多次更新或删除同一行”它指的是表 preStatus,因为似乎 sql 不知道要更新哪条记录。 ..这是我真正的问题...有什么想法吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-25
  • 2023-03-21
  • 2016-07-16
  • 2011-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多