Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Confronta due righe e identifica le colonne i cui valori sono diversi

Tu dici:

 We want to highlight the parameters that have changed since the last revision.

Ciò implica che si desidera che il display (o il report) faccia risaltare i parametri modificati.

Se hai intenzione di mostrare comunque tutti i parametri, sarebbe molto più semplice farlo a livello di codice nel front-end. Sarebbe un problema molto più semplice in un linguaggio di programmazione. Sfortunatamente, non sapendo quale sia il tuo front-end, non posso darti consigli particolari.

Se davvero non puoi farlo nel front-end ma devi ricevere queste informazioni in una query dal database (hai detto "solo SQL"), devi specificare il formato in cui desideri inserire i dati. A elenco a colonna singola delle colonne che sono cambiate tra i due record? Un elenco di colonne con un contrassegno che indica quali colonne sono state modificate o meno?

Ma ecco un modo che funzionerebbe, anche se nel processo converte tutti i tuoi campi in nvarchars prima di eseguire il confronto:

  1. Utilizza la tecnica descritta qui (dichiarazione di non responsabilità:questo è il mio blog) per trasformare i tuoi record in coppie ID-nome-valore.
  2. Unisci il set di dati risultante a se stesso su ID, in modo da poter confrontare i valori e stampare quelli che sono cambiati:

     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)