Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Comparer deux lignes et identifier les colonnes dont les valeurs sont différentes

Vous dites :

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

Cela implique que vous souhaitez que l'affichage (ou le rapport) fasse ressortir les paramètres qui ont changé.

Si vous voulez quand même afficher tous les paramètres, il serait beaucoup plus facile de le faire par programmation dans le front-end. Ce serait un problème beaucoup plus simple dans un langage de programmation. Malheureusement, ne connaissant pas votre front-end, je ne peux pas vous donner de recommandations particulières.

Si vous ne pouvez vraiment pas le faire dans le frontal mais que vous devez recevoir ces informations dans une requête de la base de données (vous avez dit "SQL uniquement"), vous devez spécifier le format dans lequel vous souhaitez que les données soient utilisées. liste à une seule colonne des colonnes qui ont changé entre les deux enregistrements ? Une liste de colonnes avec un indicateur indiquant quelles colonnes ont changé ou n'ont pas changé ?

Mais voici une façon qui fonctionnerait, bien que dans le processus, il convertisse tous vos champs en nvarchars avant de faire sa comparaison :

  1. Utilisez la technique décrite ici (avertissement :c'est mon blog) pour transformer vos enregistrements en paires ID-nom-valeur.
  2. Joignez l'ensemble de données résultant à lui-même sur l'ID, afin de pouvoir comparer les valeurs et imprimer celles qui ont changé :

     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)