Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Compare duas linhas e identifique colunas cujos valores são diferentes


Você diz:
 We want to highlight the parameters that have changed since the last revision.

Isso implica que você deseja que a exibição (ou relatório) destaque os parâmetros alterados.

Se você for mostrar todos os parâmetros de qualquer maneira, seria muito mais fácil fazer isso programaticamente no front-end. Seria um problema muito mais simples em uma linguagem de programação. Infelizmente, não sabendo qual é o seu front-end, não posso lhe dar recomendações específicas.

Se você realmente não pode fazer isso no front-end, mas precisa receber essas informações em uma consulta do banco de dados (você disse "somente SQL"), você precisa especificar o formato em que deseja os dados. lista de coluna única das colunas que mudaram entre os dois registros? Uma lista de colunas com um sinalizador indicando quais colunas foram ou não alteradas?

Mas aqui está uma maneira que funcionaria, embora no processo ele converta todos os seus campos em nvarchars antes de fazer sua comparação:
  1. Use a técnica descrita aqui (disclaimer:esse é meu blog) para transformar seus registros em pares ID-nome-valor.

  2. Junte o conjunto de dados resultante a si mesmo no ID, para que você possa comparar os valores e imprimir aqueles que foram alterados:
     with A as (    
    --  We're going to return the product ID, plus an XML version of the     
    --  entire record. 
    select  ID    
     ,   (
          Select  *          
          from    myTable          
          where   ID = pp.ID                            
          for xml auto, type) as X 
    from    myTable pp )
    , B as (    
    --  We're going to run an Xml query against the XML field, and transform it    
    --  into a series of name-value pairs.  But X2 will still be a single XML    
    --  field, associated with this ID.    
    select  Id        
       ,   X.query(         
           'for $f in myTable/@*          
           return         
           <data  name="{ local-name($f) }" value="{ data($f) }" />      
           ') 
           as X2 from A 
    )
    ,    C as (    
     --  We're going to run the Nodes function against the X2 field,  splitting     
     --  our list of "data" elements into individual nodes.  We will then use    
     -- the Value function to extract the name and value.   
     select B.ID as ID  
       ,   norm.data.value('@name', 'nvarchar(max)') as Name  
       ,   norm.data.value('@value', 'nvarchar(max)') as Value
    from B cross apply B.X2.nodes('/myTable') as norm(data))
    
    -- Select our results.
    
    select *
    from ( select * from C where ID = 123) C1
    full outer join ( select * from C where ID = 345) C2
        on C1.Name = c2.Name
    where c1.Value <> c2.Value 
      or  not (c1.Value is null and c2.Value is null)