SQL Server: сравните две таблицы с помощью UNION и Select * плюс дополнительный столбец меток

Я экспериментировал с образцом в блоге сервера Джеффа. для сравнения двух таблиц и поиска различий.

В моем случае таблицы - это резервная копия и текущие данные. Я могу получить то, что хочу, с помощью этой инструкции SQL (упрощенной за счет удаления большинства столбцов). Затем я могу увидеть строки из каждой таблицы, которые не имеют точного соответствия, и я могу увидеть, из какой таблицы они взяты.

SELECT 
   MIN(TableName) as TableName
   ,[strCustomer]
   ,[strAddress1]
   ,[strCity]
   ,[strPostalCode]
FROM 
   (SELECT 
       'Old' as TableName
       ,[JAS001].[dbo].[AR_CustomerAddresses].[strCustomer]
       ,[JAS001].[dbo].[AR_CustomerAddresses].[strAddress1]
       ,[JAS001].[dbo].[AR_CustomerAddresses].[strCity]
       ,[JAS001].[dbo].[AR_CustomerAddresses].[strPostalCode]
    FROM  
       [JAS001].[dbo].[AR_CustomerAddresses]
    UNION ALL
    SELECT 
       'New' as TableName
       ,[JAS001new].[dbo].[AR_CustomerAddresses].[strCustomer]
       ,[JAS001new].[dbo].[AR_CustomerAddresses].[strAddress1]
       ,[JAS001new].[dbo].[AR_CustomerAddresses].[strCity]
       ,[JAS001new].[dbo].[AR_CustomerAddresses].[strPostalCode]
    FROM 
       [JAS001new].[dbo].[AR_CustomerAddresses]) tmp
  GROUP BY 
     [strCustomer]
     ,[strAddress1]
     ,[strCity]
     ,[strPostalCode]
  HAVING 
     COUNT(*) = 1

Этот ответ о переполнении стека дает мне гораздо более чистый SQL-запрос, но не говорит мне, из какой таблицы взяты строки.

    SELECT * FROM [JAS001new].[dbo].[AR_CustomerAddresses]
    UNION 
    SELECT * FROM [JAS001].[dbo].[AR_CustomerAddresses]
    EXCEPT 
    SELECT * FROM [JAS001new].[dbo].[AR_CustomerAddresses]
    INTERSECT
    SELECT * FROM [JAS001].[dbo].[AR_CustomerAddresses]

Я мог бы использовать первую версию, но у меня есть много таблиц, которые мне нужно сравнить, и я думаю, что должен быть простой способ добавить столбец исходной таблицы во второй запрос. Я пробовал несколько вещей и гуглил безрезультатно. Я подозреваю, что, возможно, я просто не ищу правильную вещь, так как уверен, что на нее уже был дан ответ.

Может быть, я иду по ложному следу, и есть лучший способ сравнить базы данных?


person StillLearnin    schedule 27.08.2014    source источник


Ответы (3)


Не могли бы вы использовать следующую настройку для достижения своей цели?

SELECT 'New not in Old' Descriptor, *
FROM 
  ( 
    SELECT * FROM [JAS001new].[dbo].[AR_CustomerAddresses]
    EXCEPT
    SELECT * FROM [JAS001].[dbo].[AR_CustomerAddresses]
  ) a

UNION 

SELECT 'Old not in New' Descriptor, *
FROM 
  (
    SELECT * FROM [JAS001].[dbo].[AR_CustomerAddresses]
    EXCEPT
    SELECT * FROM [JAS001new].[dbo].[AR_CustomerAddresses]
  ) b
person AHiggins    schedule 27.08.2014

Вы не можете добавить туда имя таблицы, потому что объединение, исключение и пересечение сравнивают все столбцы. Это означает, что вы не можете различать их, добавляя имя таблицы в запрос. Группа по дает вам контроль над тем, какие столбцы учитываются при поиске дубликатов, поэтому вы можете исключить имя таблицы.

Чтобы помочь вам с большим количеством таблиц, которые вам нужно сравнить, вы можете написать запрос sql для таблиц метаданных, которые содержат имена таблиц и столбцы, и динамически генерировать команды sql для этих значений.

person Vulcronos    schedule 27.08.2014

Получите один столбец, используя имена таблиц, как показано ниже.

    SELECT MIN(TableName) as TableName
              ,[strCustomer]
              ,[strAddress1]
              ,[strCity]
              ,[strPostalCode]
          ,table_name_came
          FROM 
          (SELECT 'Old' as TableName
              ,[JAS001].[dbo].[AR_CustomerAddresses].[strCustomer]
              ,[JAS001].[dbo].[AR_CustomerAddresses].[strAddress1]
              ,[JAS001].[dbo].[AR_CustomerAddresses].[strCity]
              ,[JAS001].[dbo].[AR_CustomerAddresses].[strPostalCode]
              ,'[JAS001].[dbo].[AR_CustomerAddresses]' as table_name_came
          FROM [JAS001].[dbo].[AR_CustomerAddresses]
          UNION ALL
          SELECT 'New' as TableName
              ,[JAS001new].[dbo].[AR_CustomerAddresses].[strCustomer]
              ,[JAS001new].[dbo].[AR_CustomerAddresses].[strAddress1]
              ,[JAS001new].[dbo].[AR_CustomerAddresses].[strCity]
              ,[JAS001new].[dbo].[AR_CustomerAddresses].[strPostalCode]
          ,'[JAS001new].[dbo].[AR_CustomerAddresses]' as table_name_came
          FROM [JAS001new].[dbo].[AR_CustomerAddresses]
          ) tmp
          GROUP BY [strCustomer]
              ,[strAddress1]
              ,[strCity]
              ,[strPostalCode]
        ,table_name_came
            HAVING COUNT(*) = 1
person Adi    schedule 27.08.2014
comment
это вообще не относится к его вопросу. Что делает добавление имени таблицы (неверно, так как оно только в первом UNION), чего не делает New/Old? - person AHiggins; 27.08.2014
comment
Предложил правку; кнопка format as code предназначена для форматирования кода, а не предложений. Также поместите кавычки вокруг столбца имени таблицы во втором UNION... - person AHiggins; 27.08.2014
comment
Верно, но у него уже есть удовлетворительный метод имени таблицы: Старый/Новый. Его вопрос не в том, как заставить работать первый запрос, а в том, как сделать его проще ИЛИ изменить второй запрос, включив в него имя таблицы. - person AHiggins; 27.08.2014