Compare two rows and identify columns whose values are different

后端 未结 4 2109
忘了有多久
忘了有多久 2020-12-17 23:20

The Situation

We have an application where we store machine settings in a SQL table. When the user changes a parameter of the machine, we create a \

4条回答
  •  遥遥无期
    2020-12-17 23:55

    You say:

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

    This implies that you want the display (or report) to make the parameters that changed stand out.

    If you're going to show all the parameters anyway, it would be a lot easier to do this programmatically in the front end. It would be a much simpler problem in a programming language. Unfortunately, not knowing what your front end is, I can't give you particular recommendations.

    If you really can't do it in the front end but have to receive this information in a query from the database (you did say "SQL-only"), you need to specify the format you'd like the data in. A single-column list of the columns that changed between the two records? A list of columns with a flag indicating which columns did or didn't change?

    But here's one way that would work, though in the process it converts all your fields to nvarchars before it does its comparison:

    1. Use the technique described here (disclaimer: that's my blog) to transform your records into ID-name-value pairs.
    2. Join the resulting data set to itself on ID, so that you can compare the values and print those that have changed:

       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         
                   
             ') 
             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)
      

提交回复
热议问题