Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Vergleichen Sie zwei Zeilen und identifizieren Sie Spalten, deren Werte unterschiedlich sind

Sie sagen:

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

Das bedeutet, dass die Anzeige (oder der Bericht) die geänderten Parameter hervorheben soll.

Wenn Sie trotzdem alle Parameter anzeigen möchten, wäre es viel einfacher, dies programmgesteuert im Frontend zu tun. Es wäre ein viel einfacheres Problem in einer Programmiersprache. Da ich Ihr Frontend nicht kenne, kann ich Ihnen leider keine besonderen Empfehlungen geben.

Wenn Sie dies wirklich nicht im Frontend tun können, sondern diese Informationen in einer Abfrage von der Datenbank erhalten müssen (Sie sagten "Nur SQL"), müssen Sie das Format angeben, in dem Sie die Daten haben möchten. A einspaltige Liste der Spalten, die sich zwischen den beiden Datensätzen geändert haben? Eine Liste von Spalten mit einem Flag, das angibt, welche Spalten geändert oder nicht geändert wurden?

Aber hier ist eine Möglichkeit, die funktionieren würde, obwohl es dabei alle Ihre Felder in nvarchars konvertiert, bevor es seinen Vergleich durchführt:

  1. Verwenden Sie die hier beschriebene Technik (Haftungsausschluss:das ist mein Blog), um Ihre Datensätze in ID-Name-Wert-Paare umzuwandeln.
  2. Verbinden Sie den resultierenden Datensatz mit sich selbst auf ID, damit Sie die Werte vergleichen und die geänderten drucken können:

     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)