Search code examples
sql-servercomparerecords

SQL Server : query to compare records in a single table and return those that don't match


I am currently using SSIS to query a database and return records from the same query every night into a table in another db with a date stamp. I want to be able to use SSRS / SQL query to compare records from yesterday to the records returned from the query today and return any that don't match.

This would include:

  • New additions (new rows)
  • New deletions (rows that were there yesterday and aren't here today)
  • Any columns that may have changed between yesterday and today

An example of the data in the table is as follows:

SERVERNAME    CPUs    RAM    DISK    DATE  
==========    ====    ===    ====    ====  
Server1        1       2      20     8/8/2013  
Server2        2       4      40     8/8/2013  
Server3        2       4      40     8/8/2013  
Server1        1       2      20     9/8/2013  
Server3        2       6      40     9/8/2013  

Query comparing the differences would return (or anything similar) - I don't even mind returning 3 tables to cater for additions / deletions / changes:

SERVERNAME    CPUs    RAM    DISK    DATE  
==========    ====    ===    ====    ====  
Server2        2       4      40     8/8/2013  
NULL           NULL    NULL   NULL   9/8/2013  
Server3        2       4      40     8/8/2013  
Server3        2       6      40     9/8/2013  

Any assistance would be much appreciated!

This is my first post so apologies if formatting is messed up...


Solution

  • Assuming there can be no duplicate server names per date, you could try the following:

    WITH allservers AS (
      SELECT DISTINCT SERVERNAME AS GroupingName
      FROM YourTable
      WHERE DATE IN (@yesterday, @today)
    )
    SELECT s.GroupingName, x.*
    FROM allservers AS s
    LEFT JOIN YourTable AS y ON s.GroupingName = y.SERVERNAME AND y.DATE = @yesterday
    LEFT JOIN YourTable AS t ON s.GroupingName = t.SERVERNAME AND t.DATE = @today
    CROSS APPLY (
      SELECT @yesterday AS GroupingDate, y.*
      UNION ALL
      SELECT @today     AS GroupingDate, t.*
    ) x
    WHERE EXISTS (
      SELECT y.CPUs, y.RAM, y.DISK
      EXCEPT
      SELECT t.CPUs, t.RAM, t.DISK
    )
    ORDER BY s.GroupingName, x.GroupingDate;
    

    The output produced by this query doesn't match yours exactly but can be easily adjusted in the main SELECT clause. The main purpose of the two columns added, GroupingName and GroupingDate, is to keep relevant rows together and in a specific order (yesterday's row followed by today's).

    You can play with a live demo of the query at SQL Fiddle.