在我的SQL表中,我试图编写一个存储过程,该过程将在每个表中查找重复项,并在找到特定列时更新true或false。由于使用了外键,所以这有点复杂,我不确定最好的写法。
目标:在表A中,如果满足重复条件,则将列“ isDuplicates”(均以FALSE开始)更新为TRUE
外键:数据库中的每个表都包含来自源资料的数据,每个数据都有发布日期。没有包含SourceDate的Sources表。每个其他表都有一个Sources列,该列带有一个外键,该外键映射到它在Sources表上的条目,使我可以访问日期。
重复条件:在表A中,如果存在其他任何同名(列“ Name”)的条目(不同的主键“ Id”),另一个条目是重复项该条目稍后发布(外键。SourceDate大于当前条目)
最终,我试图创建一个表,其中'isDuplicate'= TRUE表示存在一个具有相同名称/不同ID的重复项,而另一项则在以后发布。因此,如果某样东西是重复的,但它本身就是最新版本,则应该说“ isDuplicate” = FALSE
希望这是有道理的。谢谢大家。
编辑:使用示例进行更新。
表A 具有列 NAME , SOURCE 和 ISDUPLICATE
Frank 71 False
Tom 71 False
Tom 83 False
Richard 83 False
Frank 13 False
SOURCES 表具有列 ID 和 SOURCEDATE
13 2/1/2010
71 5/1/2014
83 8/1/2014
在表A 上运行存储过程后,我期望得到以下结果:
Frank 71 False
Tom 71 True
Tom 83 False
Richard 83 False
Frank 13 True
Frank(来源13)和Tom(71)都被标记为TRUE,因为它们是另一个现有条目的旧版本。我将Tom(83)和Frank(71)设为FALSE,因为它们是我要显示的主要条目。
不仅仅是删除重复项的目的是允许用户使用功能-默认情况下,他们只会为每件商品看到一个条目,并且它将始终是最新发布的商品。但是,我还将允许他们查看他们想要的所有内容(基本上默认为仅使用isDuplicate = FALSE提取数据,但允许他们将其关闭并显示重复/旧数据)。
答案 0 :(得分:1)
我认为以下查询应能为您提供所需的信息。它通过联接表tableA
和Sources
来工作。内联相关子查询可用于检查记录是否被视为重复项:
SELECT t.Name, t.Source, CASE WHEN EXISTS (
SELECT 1
FROM tableA t1
INNER JOIN Sources s1 ON s1.ID = t1.Source
WHERE t1.Name = t.Name AND s1.SourceDate < s.SourceDate
) THEN 1 ELSE 0 END AS isDuplicate
FROM tableA
INNER JOIN Sources s ON s.ID = t.Source
第isDuplicate
列的值为0
(非重复)或1
(重复)
对于SQLServer 2017,使用窗口函数ROW_NUMBER()
:
SELECT
t.Name,
t.Source,
CASE
WHEN ROW_NUMBER() OVER(PARTITION BY t.Name ORDER BY s.SourceDate DESC) = 1 THEN 0
ELSE 1
END AS isDuplicate
FROM tableA t
INNER JOIN Sources s ON s.ID = t.Source
您可以将其放入CTE,然后将其转换为更新查询:
WITH cte AS (
SELECT
t.*,
ROW_NUMBER() OVER(PARTITION BY t.Name ORDER BY s.SourceDate DESC) AS rn
FROM tableA t
INNER JOIN Sources s ON s.ID = t.Source
) UPDATE cte SET isDuplicate = IIF(rn = 1, 0, 1)