【问题标题】:Update a column in the most recent record within a partition/group更新分区/组内最新记录中的列
【发布时间】:2016-03-26 22:51:06
【问题描述】:

问候和节日快乐!

我是 SQL 新手,我正在尝试解决一个问题。我用谷歌搜索但找不到解决方案。如果这是在错误的论坛中,我请求您将其移至适当的论坛。

提前感谢您提供的任何见解!欣赏!

我的桌子:

ID1        ID2 RECNBR ACTFLG                    
ABDCDDFDD  1   1      0                 
JHKLLLKHJ  9   1      0                
SDFKJLSDK  4   1      0              
LKJHJNHGJ  9   2      1 <-- Error (only the record with highest RECNBR for a ID2 can have ACTFLG as 1                     
SDFDSLLSD  2   1      0               
BDFDFDFDD  1   2      1                    
DSFKLKJSD  4   2      1            
LOKKJLLLH  9   3      1           
GFLDSFFGL  2   2      1

几个事实:

  1. ID1 是唯一的字母数字列,对于每条记录都是唯一的。
  2. ID2 数值,但不一定按排序顺序。
  3. RECNBR - 对于每个 ID2,从 1 开始,对于同一 ID2 的每个新记录递增 1。
  4. ACTFLG - 该字段设置为“1”以表示同一 ID2 内的最高 RECNBR。所有其他记录都应为零。
  5. 记录未按任何排序顺序。

问题:

  1. 如果您注意到 ID2 '9'。它有 3 条记录,RECNUM 为 1、2 和 3。根据事实,只有 RECNUM '3' 的 ACTFLG 可以为 '1'。但是在我的表中,我既有 RECNUM '2' 又有 '3' 和 ACTFLG '1'。

要求:

注意:我试图避免循环。我有一个使用循环的解决方案,它需要很多时间来执行。我正在尝试使用诸如 PARTITION/GROUP BY 等系统功能的一些简单的 1 或 2 行代码来执行此操作。

我可以将所有记录的ACTFLG 设置为“0”。我需要关于如何在特定 ID2 中识别具有最高 RECNUM 的记录的编码想法。一旦确定,我想将这些记录的 ACTFLG 更新为“1”。

或

识别 ID2 '9'、RECNUM '2' 等记录(有问题)并将 ACTFLG 更新为 '0'。

【问题讨论】:

  • 是哪个:sql-server 还是 mysql?请删除不相关的标签。

标签: mysql sql sql-server group-by partition


【解决方案1】:

假设 SQL Server,这是锤子:

with cte as (
   select *, row_number() over (partition by ID2 order by recnbr desc) as rn
)
update cte
set actflg = case when rn = 1 then 1 else 0 end;

这是手术刀:

with cte as (
   select *, row_number() over (partition by ID2 order by recnbr desc) as rn
)
update cte
set actflg = 1
where rn = 1
   and actflg = 0;

with cte as (
   select *, row_number() over (partition by ID2 order by recnbr desc) as rn
)
update cte
set actflg = 0
where rn <> 1
   and actflg = 1;

无论您采用哪种方法,您都应该只需要一次性清理即可。展望未来,最好保持正确的价值。

不是您要求的,而是对设计的一些观察:

  1. 如果每个 ID2 组只能激活一项,请使用唯一过滤索引强制执行该操作。类似create unique index [myFilteredIndex] on [myTable] (ID2) where (actflg = 1);
  2. actflg 是多余的,只要给定表中的其他信息,我可以为任何行推导出 actflg 的值。我承认将它存储在行中可能是一种性能优化,但它确实伴随着必须维护它的开销(正如这个问题的整个存在理由所暗示的那样)。值得一试的是,动态推导哪个是活动的,然后完全删除此列。

【讨论】:

    【解决方案2】:

    这个基本解决方案应该可以工作:(现在使用 T-SQL 语法)

    update MyTable
    set ACTFLG = 0 ;
    
    update MyTable 
    set ACTFLG = 1
    from MyTable AS T1
    where T1.RECNBR = (
      select MAX(T2.RECNBR) 
      from MYTable as T2
      where T1.ID2 = T2.ID2);
    

    它正在发挥作用:http://sqlfiddle.com/#!3/8f47b8/2

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-02
      • 1970-01-01
      相关资源
      最近更新 更多