Search code examples
sqlsql-serversql-updatecommon-table-expressionsql-server-2016

Update a table based on a combination of fields


What I've been asked to do is, if the combination of SOC_NUM & CLASS_NUM & EFF_DATE & ACCT_NUM & BEN_OPT_CD & TRANS_ID shows a value of "No Error" in the QError field, then find all records with that field combination and update the QError field to "No Error". So, in the sample table below, because at least one record with that field combination has a QError value of "No Error", all of them should.

SOC_NUM   CLASS_NUM   EFF_DATE  SITUS   STE_CD  MED_JURIS_IND   ACCT_NUM    BEN_OPT_CD  TRANS_ID    BEN_EFF_DT  Qerror                   Reportname
24674     145         1/1/2023  AL      AL      NJ              3209604     OAPIN       8992778     1/1/2022    SITUS_STATE_CODE_ERROR   SITUS_STATE_ERROR_RPT
24674     145         1/1/2023  NJ              NJ              3209604     OAPIN       8992778     1/1/2022    Missing STE_CD           SITUS_STATE_ERROR_RPT
24674     145         1/1/2023  NJ      AR      NJ              3209604     OAPIN       8992778     1/1/2022    No Error                 SITUS_STATE_ERROR_RPT
24674     145         1/1/2023  NJ      DE      NJ              3209604     OAPIN       8992778     1/1/2022    No Error                 SITUS_STATE_ERROR_RPT

The table probably has 2 million records in it. I thought about a loop, but how would I know which record I paused at if I ran an Update command in the middle of it?


Solution

  • Here is one way to do it with window functions and an updatable CTE:

    with cte as (
        select Qerror, 
            max(case when Qerror = 'No Error' then 1 else 0 end) 
                over(partition by soc_num, class_num, eff_date, acct_num, ben_opt_cd, trans_id ) has_no_error
        from mytable
    )
    update cte
    set Qerror = 'No Error'
    where has_no_error = 1 and Qerror <> 'No Error'
    

    In the CTE, the window function checks if any row in the same group has value 'No Error' in column Qerror. With this information at hand, we can then update all related rows from CTE.

    Note that the update ignores rows that already have the correct value, for efficiency. If Qerror may be null, the where clause should be adapted:

    with cte as (...)
    update cte
    set Qerror = 'No Error'
    where has_no_error = 1 and (Qerror is null or Qerror <> 'No Error')