복붙노트

[SQL] 사용 LEFT 조인 할 때 어떻게이 스크립트는 테이블을 갱신한다?

SQL

사용 LEFT 조인 할 때 어떻게이 스크립트는 테이블을 갱신한다?

이 스크립트의 결과는 정확하지만 이해하지 못하는 것 같습니다 왜 열 BetaStatus 남아 'NOK'

에 대해서는 '베타', 첫 번째 행 (베타 = NOK)는 Summary.BetaStatus @ NOK으로 업데이트 할 것입니다. 그러나 나는 @testTable의 마지막 두 행이 확인에 NOK의 뒤쪽에서 BetaStatus를 업데이트 할 것이라고 생각했다. 난 그냥이 'NOK가'실제로 처리 할 수있는 마지막 행, 따라서 값이다 우연의 일치가 아니라고 확신하고 싶습니다.

declare @testTable table 
(
    id int,
    Pgroup varchar(10),
    Pstatus varchar(3)
)
insert into @testTable select 3, 'Alpha', 'OK'
insert into @testTable select 3, 'Beta',  'NOK'
insert into @testTable select 3, 'Gamma', 'OK'
insert into @testTable select 3, 'Beta',  'OK'
insert into @testTable select 3, 'Beta',  'OK'

declare @Summary table
(
    id int,
    AlphaStatus varchar(3),
    BetaStatus varchar(3),
    GammaStatus varchar(3)
)
insert into @Summary (id) select 3

update @Summary 
set
    AlphaStatus = ISNULL(rA.Pstatus, AlphaStatus),
    BetaStatus = ISNULL(rB.Pstatus,  BetaStatus),
    GammaStatus = ISNULL(rG.Pstatus, GammaStatus)
from @Summary t
left join @testTable rA on rA.id = t.ID AND rA.Pgroup = 'Alpha'
left join @testTable rB on rB.id = t.ID AND rB.Pgroup = 'Beta'
left join @testTable rG on rG.id = t.ID AND rG.Pgroup = 'Gamma'

select * from @summary

물어 그 이유는 이전했다 'NOK'경우, AlphaStatus는, BetaStatus는 GammaStatus는 'OK'으로 다시 변경해야하는 것이 아닌 모든 id 인 것을입니다. 이 'NOK'업데이트 일단 관계없이 다음에 오는 어떤 그런 식으로 남아있다.

대안은 'OK'값 @Summary 업데이트 한 다음 'NOK'로 또 다른 갱신을 할 수 있었다. 그런 식으로 나는 'NOK가'교체되지 않습니다 것을 알고있다. 그러나이 작품 있다면, 차라리이를 사용하십시오.

나는 내부 조인 사용하는 경우 그리고 두 번째 질문으로 왜 제대로 업데이트 작동하지 않는 이유는 무엇입니까?

감사.

해결법

  1. ==============================

    1.하자가 반환 대신 업데이 트의 선택을 확인

    하자가 반환 대신 업데이 트의 선택을 확인

    select 
         AlphaStatus = ISNULL(rA.Pstatus, AlphaStatus),
         BetaStatus  = ISNULL(rB.Pstatus,  BetaStatus),
         GammaStatus = ISNULL(rG.Pstatus, GammaStatus)
    from @Summary t
    left join @testTable rA on rA.id = t.ID AND rA.Pgroup = 'Alpha'
    left join @testTable rB on rB.id = t.ID AND rB.Pgroup = 'Beta'
    left join @testTable rG on rG.id = t.ID AND rG.Pgroup = 'Gamma'
    

    결과:

    AlphaStatus     BetaStatus  GammaStatus
    OK              NOK         OK
    OK              OK          OK
    OK              OK          OK
    

    이제 UPDATE를 수행하려고

    update @Summary 
    set
        AlphaStatus = ISNULL(rA.Pstatus, AlphaStatus),
        BetaStatus  = ISNULL(rB.Pstatus,  BetaStatus),
        GammaStatus = ISNULL(rG.Pstatus, GammaStatus)
    from @Summary t
    left join @testTable rA on rA.id = t.ID AND rA.Pgroup = 'Alpha'
    left join @testTable rB on rB.id = t.ID AND rB.Pgroup = 'Beta'
    left join @testTable rG on rG.id = t.ID AND rG.Pgroup = 'Gamma'
    

    업데이트 테이블 @Summary에 포함 된 후 :

    id  AlphaStatus     BetaStatus  GammaStatus
    3   OK              NOK         OK
    

    난 당신이 얻고 싶었다 가정 :

    id  AlphaStatus     BetaStatus  GammaStatus
    3   OK              OK      OK
    

    그러나 UPDATE는 여러 일치하는 경우 결과가 일치하지 않을 수 있습니다 그것은 부분적으로 테이블 주문 또는 실제 실행 계획을 기반으로, 그런 식으로 작동하지 않습니다.

    참조 : FROM하자 지원 중단 UPDATE! 휴고 Kornelis로

    너무 대신 테이블 변수 사용 테이블의 불일치를 확인하고 클러스터 된 인덱스를 만들 :

    SqlFiddleDemo

    CREATE TABLE testTable(id int,
        Pgroup varchar(10),
        Pstatus varchar(3));
    
    CREATE CLUSTERED INDEX clx_name
    ON  testTable(PStatus DESC);
    
    /* or */
    CREATE CLUSTERED INDEX clx_name
    ON  testTable(PStatus ASC);  
    

    당신은 예를 들어 MERGE를 사용하는 경우 :

    ;WITH cte as
    (SELECT 
       ra.id
       ,AlphaStatus = rA.Pstatus
       ,BetaStatus = rB.Pstatus
       ,GammaStatus = rG.Pstatus
    from @Summary t
    left join @testTable rA on rA.id = t.ID AND rA.Pgroup = 'Alpha'
    left join @testTable rB on rB.id = t.ID AND rB.Pgroup = 'Beta'
    left join @testTable rG on rG.id = t.ID AND rG.Pgroup = 'Gamma'
    )
    MERGE @Summary AS TGT
    USING (SELECT * FROM cte ) AS  SRC
       ON TGT.id = SRC.id
    WHEN MATCHED THEN
       UPDATE
       SET 
        AlphaStatus = ISNULL(src.AlphaStatus, tgt.AlphaStatus),
        BetaStatus  = ISNULL(src.BetaStatus,  tgt.BetaStatus),
        GammaStatus = ISNULL(src.GammaStatus, tgt.GammaStatus);
    

    이 허용되지 않는 것이 분명 오류 메시지가 나타납니다 :

  2. from https://stackoverflow.com/questions/32385665/how-is-this-script-updating-table-when-using-left-joins by cc-by-sa and MIT license