Обновите oldID для записей рекурсивно - PullRequest
1 голос
/ 03 февраля 2012

Я задал очень похожий вопрос здесь , но мне нужно больше предварительных запросов сейчас.Ситуация такова, у нас около 20 000 записей клиентов.Клиенты могут обновлять, и мы просто создаем новую запись для него.Нет точного отслеживания того, какая запись была фактически обновлена.Теперь мы добавили поле old ID, и я хочу заполнить его точной старой записью.Теперь, если это будет продлено один раз, это позаботится о моем старом вопросе, и я могу это сделать.Проблема в том, что если запись обновлялась 3 или более раз, мне нужно найти точную логику того, как самая старая запись перешла на самую новую.Для этого у нас нет установленного правила, но обычно я следую customer start date (и сам идентификатор проливает свет на то, какая запись появилась первой), и пока что будет использовать 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, но мне потребовалось бы некоторое время, чтобы сделать это, если я смогу сделать это в первую очередь.

Ответы [ 3 ]

1 голос
/ 04 февраля 2012

Второй ответ: Вы можете обновить столбец 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
1 голос
/ 03 февраля 2012

Я знаю, что вам, вероятно, не понравится мой ответ, но я бы изменил структуру базы данных и добавил бы 2 таблицы.Это улучшило бы скорость и уменьшило бы избыточные данные в вашей базе данных.

Table 1
Contract
contract_id  |   startdate | meter_no  |   cust_no

Table 2
Contract_detail
contract_id  | startdate   | enddate 

Вот как вы можете заполнить таблицы старыми данными: я предполагаю, что у каждого Заказчика есть только один контракт, если у него болееодна запись в таблице клиентов, затем он обновляется.

Если вы определили столбец contract_id в контракте как автоматическое значение, попробуйте следующее.

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
0 голосов
/ 06 февраля 2012

Фактический запрос, который я использовал и который работал отлично, был. Это было возможно только после ответа @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
...