3

我在表中有重复的记录。我只需要能够识别一个唯一标识符,以便可以将其从表中删除。

我知道有重复的唯一方法是从列中subjectdescription所以如果至少有 2 个相同的主题和相同的描述,我需要删除一个并留下一个。

所以我能够获得重复记录的列表,但我无法获得能够删除它的唯一标识符。

这是我为识别重复记录所做的。

SELECT 
    p.accountid, p.subject, p.description, count(*) AS total
FROM
    activities AS p 
WHERE     
    (p.StateCode = 1) AND p.createdon >= getdate()-6
GROUP BY 
    p.accountid, p.subject, p.description
HAVING 
    count(*) > 1
ORDER BY 
    p.accountid

有一列record_id保存每条记录的唯一标识符。但是如果我添加record_id到我的选择语句中,那么我不会得到任何结果,因为不可能有重复的唯一标识符

如何获得record_id使用 SQL Server?

注意:record_id 不是整数,它类似于“D32B275B-0B2F-4FF6-8089-00000FDA9E8E”

谢谢

4

4 回答 4

4

我喜欢 SQL Server 的一个很好的特性是使用带有updatedelete语句的 CTE。

您正在寻找重复的记录,并且可能希望保留最低或最高的记录record_id。您可以获取计数和 id 以继续使用 CTE 和窗口函数:

with todelete as (
    SELECT p.accountid, p.subject, p.description,
           COUNT(*) over (partition by p.accountid, p.subject, p.description) as total,
           MIN(record_id) over (partition by p.accountid, p.subject, p.description) as IdToKeep
    FROM activities AS p 
    WHERE (p.StateCode = 1) AND p.createdon >= getdate()-6
   )
delete from todelete
    where total > 1 and record_id <> IdToKeep;

最后一个where子句只是使用逻辑来选择要删除的正确行。

我应该补充一点,如果您只想要将被删除的列表,您可以使用类似的查询:

with todelete as (
    SELECT p.accountid, p.subject, p.description,
           COUNT(*) over (partition by p.accountid, p.subject, p.description) as total,
           MIN(record_id) over (partition by p.accountid, p.subject, p.description) as IdToKeep
    FROM activities AS p 
    WHERE (p.StateCode = 1) AND p.createdon >= getdate()-6
   )
select *
from todelete
 where total > 1 and record_id <> IdToKeep;

over函数表示一个函数正在用作窗口函数。这个想法很简单。 返回子句Count(*) over中字段具有相同值的所有记录的计数。partition它很像聚合函数,除了你得到每一行的值。这类函数非常强大,建议大家多多了解一下。

于 2013-06-05T20:53:49.100 回答
0

也许是这样的?

SELECT max(p.record_id), p.accountid, p.subject, p.description, count(*) AS total
FROM activities AS p 
WHERE (p.StateCode = 1) AND p.createdon >= getdate()-6
GROUP BY p.accountid, p.subject, p.description
HAVING count(*) > 1
ORDER BY p.accountid
于 2013-06-05T20:53:01.497 回答
0

在我看来,您需要先进行内部查询,然后加入更大的表以获得您想要的。

SELECT ALL
    *
FROM (SELECT p.accountid
  FROM activities AS p
  WHERE p.statecode = 1 AND p.createdon >= getdate()-6
  GROUP BY p.accountid
  HAVING count(*) > 1) AS x
JOIN activities AS a ON x.accountid = a.accountid
ORDER BY p.accountid
于 2013-06-05T20:54:08.940 回答
0

尝试这个:

;with recordsToDelete as (
SELECT 
     recordId
    ,Row_Number() OVER(partition p.subject, p.description) as rowNum
FROM activities AS p 
)

select
*
from recordsToDelete
where rowNum > 1

如果看起来正确,您可以将 select 替换为:

delete from recordsToDelete
    where rowNum > 1
于 2013-06-05T21:23:02.850 回答