【问题标题】:Identify duplicate records and update a flag on them识别重复记录并更新它们的标志
【发布时间】:2017-11-03 06:33:05
【问题描述】:

有一张桌子——我们称之为DemoReport——有下面的一组键。

  • YearOfGeneration
  • WeekOfGeneration
  • Key3
  • Key4

还有一列用于表示最新记录的标志。此列不是键的一部分。如果此标志为真,则特定记录是最新记录。 当通过代码创建记录时,默认情况下此标志设置为 true。

示例记录应如下所示:

    | *YearOfGeneration* | *WeekOfGeneration* | *Key3*        | *Key4*      | *Latest*
    | 2017               | 2                  | Key3Sample1   | Key4Sample1 | 1
    | 2017               | 3                  | Key3Sample1   | Key4Sample1 | 1

Key3Key4 相同时,任何记录都应该标记为最新,并且YearOfGenerationWeekOfGeneration 应该是最新的。所以在上面的例子中,第二条记录的最新标志应该设置为真,第一条记录应该设置为假。

要求是编写一个 sql 来识别和更新记录以取消设置非最新记录上的“最新”标志。

有人可以建议sql应该怎么写吗?

【问题讨论】:

  • 您为什么要在表本身中存储关于哪一行是最新的信息?这应该是查找“最新”行的某些视图或查询的一部分(取决于业务需求);我们通常不会将聚合结果存储在 OLTP 系统中的表中。

标签: oracle duplicates


【解决方案1】:
UPDATE DemoReport 
SET latest = 0 -- Whatever older record should be marked as 
WHERE 
(YearOfGeneration ||LPAD(WeekOfGeneration,2,'0')|| Key3||Key4) 
NOT IN 
(SELECT 
MAX(YearOfGeneration || LPAD(WeekOfGeneration,2,'0'))|| Key3 || Key4
FROM DemoReport
GROUP BY Key3, Key4);

Commit;

【讨论】:

  • 如果 2016 年的最大生成周数为 10,而 2017 年的最大生成周数为 6(显然对于相同的 key3 和 key4),这将如何工作?
  • 感谢您撰写此答案。是的,我同意,此解决方案适用于所有周都属于同一年的一般情况。但是,当一条记录的周数为 52,年份为 2017 年,另一条记录的周数为 1,年份为 2018 年时。您能否为此提出可能的解决方案?
  • 它也应该适用于这种情况,因为查询将排除 201752 和 201801 之间的最大值(LPAD 将添加 0)对于 Key3 和 Key4 的相同分组。它将排除后者。
【解决方案2】:

您可以使用row_number ()获取有效记录,并使用合并语句更新相应记录。

MERGE INTO DemoReport m
     USING (SELECT d.*,
                   CASE
                      WHEN     ROW_NUMBER ()
                               OVER (
                                  PARTITION BY key3, key4
                                  ORDER BY
                                     YearOfGeneration DESC,WeekOfGeneration DESC) !=
                                  1
                           AND LATEST = 1
                      THEN
                         0
                      ELSE
                         LATEST
                   END
                      new_latest
              FROM DemoReport d) s
        ON (    m.key3 = s.key3
            AND m.key4 = s.key4
            AND m.WeekOfGeneration = s.WeekOfGeneration)
WHEN MATCHED
THEN
   UPDATE SET m.latest = s.new_latest;

【讨论】:

  • 为什么将 YearOfGeneration 和 WeekOfGeneration 串联?例如,如果表中有第 2 周和第 11 周,它将无法正常工作。我想您想加入所有四个关键列,而不仅仅是三个。
  • @GoranStefanović:谢谢,我忘了添加TO_NUMBER 但是问题仍然是,如果 OP 在 2017 年使用 week1,week2, week3 ...week52 ,那么它才会起作用。但如果是 week1..week4,week1,week2.... 它不会。操作人员需要澄清它。
  • 我根本不会使用任何转换 - 只需按 YearOfGeneration DESC、WeekOfGeneration DESC 进行排序就足够了。我同意 OP 应该澄清 WeekOfGeneration 的填充方式 - 基于我的假设是每年 1..52 的问题
  • @GoranStefanović:哦,是的。毕竟它们应该是数字。无论如何,感谢您指出它。我过度概括了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-01
  • 1970-01-01
  • 2020-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-04
相关资源
最近更新 更多