自引用自身的滞后命令

问题描述 投票:0回答:2

我希望使用 LAG 函数沿着表内容的长度重复填充字段。这是我的情况。我正在从一个笨拙的源读取数据,该源提取看起来像这样的行 --

Split_Name_In_Heading         ID
Central Scheduling (contd)    171081
NULL                          171083
NULL                          171088
NULL                          171091
NULL                          171094
NULL                          171097

有数千个这样的字段,其中我有兴趣抓取的字段,Split_Name_In_Heading,并将其级联到后面的所有记录。我想执行此操作,直到找到新的 Split_Name_In_Heading,然后开始复制该名称。所以我这样做了--

select
  case when Split_Name_In_Heading is null 
       then lag(Split_Name) over (order by ID)
       else REPLACE(SPLIT_NAME_IN_HEADING, ' (contd)', '') end as Split_Name,
  Split_Name_In_Heading,
  ID
--into #Pass_1
from #Clean_List
order by ID

请注意,我正在尝试创建一个新字段 Split_Name,它引用前一行的 Split_Name。它是自我引用的。 (它也删除了 Split_Name_In_Heading 字段末尾的垃圾,但这很好)我想要的结果 --

Split_Name            Split_Name_In_Heading           ID
Central Scheduling    Central Scheduling (contd)      171081
Central Scheduling    NULL                            171083
Central Scheduling    NULL                            171088
Central Scheduling    NULL                            171091
Central Scheduling    NULL                            171094
Central Scheduling    NULL                            171097

我的代码产生错误。我无法在字段 Split_Name 的定义中引用字段 Split_Name。当我尝试使用 Split_Name_In_Heading 引导加载第二遍的值时,它只会为后续一条记录创建值。之后这些值保持为空。

这是从 WebFOCUS 代码进行的转换,这是一件超级简单的事情,我们已经在代码库中完成了数十次,所以我正在寻找一个通用的解决方案。我需要全部更换。 LAG 可以以某种方式自引用自己的字段吗?我已经看到几个线程使用临时表和前一行的引用,但我还没有找到一种简单的方法来实现这一点,因为它们不会继续将值复制到多行集合中有空值的。有时可能高达 100。

sql-server lag
2个回答
0
投票

假设ID是这里的SEQUENCE,我们可以使用窗口函数

sum() over ()
来创建分组,然后我们使用窗口函数
max() over()
作为最终值

示例

Declare @YourTable Table ([Split_Name_In_Heading] varchar(50),[ID] int)  Insert Into @YourTable Values 
 ('Central Scheduling (cont''d)',171081)
,(NULL,171083)
,(NULL,171088)
,(NULL,171091)
,(NULL,171094)
,(NULL,171097)
,('Other Item (cont''d)',181081)  -- added another example
,(NULL,181083);                   -- added another example
 

with cte as (
Select *
      ,Flg = sum(case when [Split_Name_In_Heading] is not null then 1 else 0 end) over (order by ID)
 from @YourTable
)
Select Split_Name = replace(max([Split_Name_In_Heading]) over (partition by Flg),' (cont''d)','')
      ,[Split_Name_In_Heading]
      ,ID
 From cte
 Order by ID

结果

Split_Name          Split_Name_In_Heading       ID
Central Scheduling  Central Scheduling (cont'd) 171081
Central Scheduling  NULL                        171083
Central Scheduling  NULL                        171088
Central Scheduling  NULL                        171091
Central Scheduling  NULL                        171094
Central Scheduling  NULL                        171097
Other Item          Other Item (cont'd)         181081
Other Item          NULL                        181083

0
投票

您可以在此处实现一个简单的相关子查询作为表表达式,然后您可以更新该表表达式。

示例:

update t set 
  name = NewName
from (
    select *, (
        select top(1) name 
        from t t2
        where t2.name is not null and t2.id < t.id
        order by id desc
    ) NewName
    from t
    where name is null
)t;

查看演示小提琴

© www.soinside.com 2019 - 2024. All rights reserved.