【问题标题】:Update oldID for the records recursively递归更新记录的 oldID
【发布时间】:2012-02-26 06:29:00
【问题描述】:

我问了一个非常相似的问题here,但我现在需要更高级的查询。情况是,我们有大约 20,000 条客户记录。客户可以续订,我们只需为其创建新记录。没有确切的追溯记录实际更新。现在我们添加了old ID 字段,我想用确切的旧记录填充它。现在如果它更新一次,那已经解决了我的老问题,我可以做到。问题是如果一条记录被更新了 3 次或更长时间,我必须找到最旧记录如何跳到最新记录的确切逻辑。为此,我们没有固定的规则,但通常我遵循customer start date(ID 本身会发出一些信息),现在将使用customer start date 填充所有记录。我在这里包含了一个测试用例

create table #customer (
id int not null primary key identity,
cust_no varchar(12),
meter_no varchar(10),
startdate smalldatetime,
enddate smalldatetime,
oldid int null
)

insert into #customer values('AA111222','1111','2008-01-01', '2008-03-01',null) 
insert into #customer values('AA111222','1111','2009-02-01', '2009-05-01',null) 
insert into #customer values('AA111222','1111','2008-03-01', '2008-12-01',null) 
insert into #customer values('AA111222','1111','2009-05-01', '2009-07-01',null) 
insert into #customer values('AA111222','1111','2009-08-01', '2009-11-01',null) 
insert into #customer values('AA111222','1111','2010-01-01', '2010-04-01',null) 
insert into #customer values('AA111222','1111','2010-07-01', '2011-07-01',null) 
insert into #customer values('AA111222','1111','2011-03-01', '2011-07-01',null) 
insert into #customer values('AA111222','1111','2011-07-01', '2012-07-01',null) 

-- I want this result in the last column

id   cust_no      meter_no   startdate      enddate        oldid           
---- ------------ ---------- -------------- -------------- -------         
1    AA111222     1111       2008-01-01     2008-03-01     base                      
2    AA111222     1111       2009-02-01     2009-05-01     3 
3    AA111222     1111       2008-03-01     2008-12-01     1            
4    AA111222     1111       2009-05-01     2009-07-01     2            
5    AA111222     1111       2009-08-01     2009-11-01     4            
6    AA111222     1111       2010-01-01     2010-04-01     5            
7    AA111222     1111       2010-07-01     2011-07-01     6            
8    AA111222     1111       2011-03-01     2011-07-01     7            
9    AA111222     1111       2011-07-01     2012-07-01     8    

请注意,我们很欣赏不同的做法,所以我也可以学到一些东西。到目前为止,我已经研究了 CTE、Join、Cursor,但如果我能做到的话,我需要一些时间才能做到。

【问题讨论】:

  • 我不明白你到底想要什么结果。你想查询表吗,你粘贴了。还是特定的列?
  • 哦,忘了所有领域。在我发布的输出中,所有列都是原始的。我想要更改/更新的唯一列是 OLDID。其余的只是查询的一部分。 需要在那里吗。
  • @Thecrocodilehunter 我不明白oldid 是如何填充的,它的规则是什么?没有规则是不可能分配任何东西的。你的例子是怎么做的?
  • 更新记录时,其所有基本内容都会复制到新记录中。因此,在上面的示例代码中,cust_nometer_no 延续到新记录(在实际表中,更多记录),但新记录的客户 startdate 不同。因此,新记录 oldid 应该与从中复制内容的记录的 ID 匹配。我认为这很明显。

标签: sql sql-server-2005 join cursor


【解决方案1】:

第二个答案: 您可以使用以下语句更新 old_id 列!

 Update #customer
 SET oldid =
        (Select TOP 1 c_old.id from #customer c_old
          where c_old.enddate <= #customer.startdate
          and c_old.cust_no = #customer.cust_no
          and c_old.meter_no = #customer.meter_no
          and c_old.enddate = 
                           (
                             SELECT max(c.enddate) FROM #customer c
                               where c_old.cust_no = c.cust_no
                               and c_old.meter_no = c.meter_no
                               and #customer.startdate >= c.enddate
                            ) 
          )
  from #customer
 go

【讨论】:

  • 我在 #customer 表上运行了您的上述查询,但它根本没有更新 oldid
  • 好的,我会在我的服务器上看看。
  • 它现在可以工作了。但是我的逻辑和你的不一样。我不知道我是否正确。但是我认为追随者的开始日期必须在旧值的结束日期之后。
  • 这太棒了。它几乎可以工作,但记录 6 和 7 都具有相同的 oldid,应该不同。我会调查的。
  • 就是因为数据有误,如果我理解正确的话。我的规则是:获取最新的结束日期,其中结束日期小于或等于当前开始日期。对于 id 8,oldid 也是 6,因为 7 的结束日期晚于 8 的开始日期。
【解决方案2】:

我知道,您可能不喜欢我的回答,但我会更改数据库的设计并添加 2 个表。 它将提高速度并减少数据库中的冗余数据。

Table 1
Contract
contract_id  |   startdate | meter_no  |   cust_no

Table 2
Contract_detail
contract_id  | startdate   | enddate 

以下是使用旧数据填充表的方法: 我假设每个客户只有一份合同,如果他在客户表中有多个条目,那么他会续签。

如果您将contract中的contract_id列定义为autovalue,请尝试以下操作。

This inserts for every cust_no and meter_no combination one entry.

Insert into contract
(cust_no, startdate, enddate, meter_no)
Select distinct cust_no
       ,Min (startdate)
       ,Max (enddate)
       ,meter_no
from customer
Group by cust_no, meter_no
GO

Insert into contract_detail
(contract_id, cust_no, startdate, enddate)
Select co.contract_id
       ,co.cust_no
       ,cu.startdate
       ,cu.enddate 
from contract co
inner join customer cu on co.cust_no = cu.cust_no 
           and co.meter_no = cu.meter_no
GO

【讨论】:

  • 不,任何事情都值得赞赏。但这里真正的问题是为旧记录填充contract_id。我该怎么做。
【解决方案3】:

我使用并且运行良好的实际查询是。只有在@chris 回答之后才有可能。这是他的修改版。

 Update #customer
 SET oldid =
        (Select TOP 1 c_old.id from #customer c_old
          where c_old.startdate < #customer.startdate
          and c_old.cust_no = #customer.cust_no
          and c_old.meter_no = #customer.meter_no
          and c_old.id != #customer.id
          order by c_old.startdate desc
          )
  from #customer

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-29
    • 1970-01-01
    • 1970-01-01
    • 2020-12-04
    • 2020-09-05
    • 2012-03-17
    • 2010-09-21
    • 1970-01-01
    相关资源
    最近更新 更多