2016-03-02 78 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 

讓我知道,如果這有助於..