2016-03-02 67 views
1

以下循环根据同一表中的其他记录的存在情况有条件地设置@EndDate。基本上,如果给定ReferenceTypeId和每个PersonId,KeepId和RemoveId至少存在一条记录,我们只想将当前日期分配给@EndDate。不带游标的更新语句中的条件集

如何在没有循环的情况下编写此Update语句。

DECLARE ReferenceType_Cursor CURSOR FOR 
    SELECT ID FROM CORE.PersonExternalReferenceType 
    OPEN ReferenceType_Cursor 
    FETCH NEXT FROM ReferenceType_Cursor INTO @RefTypeId 

    WHILE @@FETCH_STATUS = 0 
    BEGIN 
     SET @ENDDATE = NULL 

     IF(EXISTS (SELECT 1 FROM CORE.PersonExternalReferences WHERE ReferenceTypeId = @RefTypeId AND PersonId = @KeepId) AND 
      EXISTS (SELECT 1 FROM CORE.PersonExternalReferences WHERE ReferenceTypeId = @RefTypeId AND PersonId = @RemoveId)) 
     BEGIN 
      SET @ENDDATE  = @CURRENTDATE 
     END 

     UPDATE CORE.PersonExternalReferences 
     SET 
      PersonId  = @KeepID, 
      ModifiedBy  = @USERNAME, 
      ModifiedDate = @CURRENTDATE, 
      StartDate  = COALESCE(StartDate,CreatedDate,@STARTDATE), 
      EndDate   = @ENDDATE 
     WHERE ReferenceTypeId = @RefTypeId AND PersonId = @RemoveID 

    FETCH NEXT FROM ReferenceType_Cursor INTO @RefTypeId 
    END 
    CLOSE ReferenceType_Cursor 
    DEALLOCATE ReferenceType_Cursor 

回答

1

所以我只想澄清你的要求:

您想要更新每个PersonExternalReferences,其中PersonId = @RemoveID。

对于每个记录,检查是否存在具有相同ReferenceTypeId和PersonId = @KeepId的另一个PersonExternalReferences 。如果存在,则设置EndDate = @ENDDATE,否则设置EndDate = null。

为了确保它是工作代码,我创建了一个简化的准备运行示例。

建立的模式是:

create table PersonExternalReferenceType (
    id varchar(100) 
) 
go 

create table PersonExternalReferences (
    PersonId int, 
    ReferenceTypeId varchar(100), 
    ModifiedDate datetime,  
    EndDate datetime   
) 
go 

insert PersonExternalReferenceType 
values ('foo'),('bar') 
; 

insert PersonExternalReferences 
values 
(1,'foo',null,null), 
(2,'foo',null,null), 
(3,'foo',null,null), 
(4,'bar',null,null) 
; 

实际的更新语句是

declare @KeepId int = 1; 
declare @RemoveId int = 2; 

update PersonExternalReferences 
set ModifiedDate = getdate(), 
    EndDate = case when exists (
    select 1 from PersonExternalReferences as other 
    where other.PersonId = @KeepId 
    and other.ReferenceTypeId = PersonExternalReferences.ReferenceTypeId 
) then getdate() else null end 
where PersonId = @RemoveId; 

,然后运行再次使用

declare @KeepId int = 3; 
declare @RemoveId int = 4; 

而最终的结果是

+----------+-----------------+-------------------------+-------------------------+ 
| PersonId | ReferenceTypeId |  ModifiedDate  |   EndDate   | 
+----------+-----------------+-------------------------+-------------------------+ 
|  1 | foo    | NULL     | NULL     | 
|  2 | foo    | 2016-03-03 10:27:40.507 | 2016-03-03 10:27:40.507 | 
|  3 | foo    | NULL     | NULL     | 
|  4 | bar    | 2016-03-03 10:27:40.517 | NULL     | 
+----------+-----------------+-------------------------+-------------------------+ 
0

@CURRENTDATE

UPDATE CORE.PersonExternalReferences 
 
     SET 
 
      PersonId  = @KeepID, 
 
      ModifiedBy  = @USERNAME, 
 
      ModifiedDate = @CURRENTDATE, 
 
      StartDate  = COALESCE(StartDate,CreatedDate,@STARTDATE), 
 
      EndDate   = 
 
case when (ReferenceTypeId = @RefTypeId 
 
AND PersonId = @KeepId 
 
and PersonID = @RemoveId) then 
 
@CURRENTDATE 
 
else null end 
 
    /*Then you don't need to filter at all if you wanna loop trought whole table... WHERE ReferenceTypeId = @RefTypeId AND PersonId = @RemoveID 
 
*/

+0

我仍然需要遍历所有ReferenceTypeIds – navig8tr

0

我对你有两个解决方案。您只需编辑分区列,其中列根据自己的需要:

update a 
set a.enddate = @enddate 
from abc as a 
where ReferenceTypeId = @RefTypeId AND PersonId = @RemoveID and 
exists(select 1 from abc as b where b.ReferenceTypeId = a.ReferenceTypeId group by ReferenceTypeId,PersonId,KeepId,RemoveId having count(*) >1) 

和另一个问题:

update a 
set a.enddate = @enddate 
from 
(
select *, count(*) over (partition by ReferenceTypeId,PersonId,KeepId,RemoveId) as rn 
from abc 
) as a 
where a.rn > 1 and ReferenceTypeId = @RefTypeId AND PersonId = @RemoveID 

让我知道,如果这有助于..