SQL сравнивает данные из двух таблиц - PullRequest
62 голосов
/ 05 января 2011

У меня есть 2 таблицы TableA и TableB, которые имеют одинаковый формат столбца, например обе таблицы TableA и TableB имеют столбцы

A B C D E F 

где A и B - первичные ключи.

Как написать SQL, чтобы проверить, что если TableA и TableB, которые имеют одинаковые первичные ключи, содержат абсолютно одинаковое значение в каждом столбце.

Это означает, что эти две таблицы имеют абсолютно одинаковые данные.

Ответы [ 16 ]

59 голосов
/ 05 января 2011

Вы должны иметь возможность "МИНУС" или "ИСКЛЮЧИТЬ" в зависимости от разновидности SQL, используемой вашей СУБД.

select * from tableA
minus
select * from tableB

Если запрос не возвращает строк, данные точно такие же.

44 голосов
/ 11 сентября 2013

Использование реляционных операторов:

SELECT * FROM TableA
UNION 
SELECT * FROM TableB
EXCEPT 
SELECT * FROM TableA
INTERSECT
SELECT * FROM TableB;

Измените EXCEPT на MINUS для Oracle.

Немного примечательный момент: вышеупомянутое опирается на приоритет оператора, который в соответствии со стандартом SQL зависит от реализации, поэтому YMMV.Он работает для SQL Server, для которого приоритет имеет:

  1. Выражения в скобках
  2. INTERSECT
  3. EXCEPT и UNION вычисляются слева направоверно.
16 голосов
/ 05 января 2011

диетбудда имеет хороший ответ. В тех случаях, когда у вас нет MINUS или EXCEPT, один из вариантов - объединить все таблицы, сгруппировать их по всем столбцам и убедиться, что есть все из двух:

SELECT col1, col2, col3
FROM
(SELECT * FROM tableA
UNION ALL  
SELECT * FROM tableB) data
GROUP BY col1, col2, col3
HAVING count(*)!=2
6 голосов
/ 09 августа 2016
SELECT c.ID
FROM clients c
WHERE EXISTS(SELECT c2.ID 
FROM clients2 c2
WHERE c2.ID = c.ID);

Вернет все идентификаторы, которые одинаковы в обеих таблицах. Чтобы получить различия, измените EXISTS на NOT EXISTS.

3 голосов
/ 20 мая 2016

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

DECLARE @table1 NVARCHAR(80)= 'table 1 name'
DECLARE @table2 NVARCHAR(80)= 'table 2 name'
DECLARE @sql NVARCHAR (1000)

SET @sql = 
'
SELECT ''' + @table1 + ''' AS table_name,* FROM
(
SELECT * FROM ' + @table1 + '
EXCEPT
SELECT * FROM ' + @table2 + '
) x

UNION 

SELECT ''' + @table2 + ''' AS table_name,* FROM 
(
SELECT * FROM ' + @table2 + '
EXCEPT
SELECT * FROM ' + @table1 + '
) y
'

EXEC sp_executesql @stmt = @sql
1 голос
/ 21 января 2019

Вы можете найти различия между 2 таблицами, используя комбинацию вставки всего и полного внешнего соединения в Oracle. В sql вы можете извлечь различия с помощью полного внешнего соединения, но кажется, что вставка all / first не существует в sql! Следовательно, вместо этого вы должны использовать следующий запрос:

select * from A
full outer join B on
A.pk=B.pk
where A.field1!=B.field1
or A.field2!=B.field2 or A.field3!=B.field3 or A.field4!=B.field4 
--and A.Date==Date1

Хотя использование «ИЛИ» в предложении where не рекомендуется и обычно приводит к снижению производительности, вы все равно можете использовать приведенный выше запрос, если ваши таблицы не являются массивными. Если есть какой-либо результат для вышеупомянутого запроса, это точно различия двух таблиц, основанные на сравнении полей 1,2,3,4. Для повышения производительности запроса вы также можете отфильтровать его по дате (см. Прокомментированную часть)

1 голос
/ 04 октября 2013

просто для завершения, процесс сохранен с использованием метода кроме, чтобы сравнить 2 таблицы и дать результат в одной и той же таблице с состоянием 3 ошибок, таблица ADD, DEL, GAP должна иметь один и тот же PK, вы объявляете 2 таблицы и поля для сравнения 1или обе таблицы

Просто используйте вот так ps_TableGap 'tbl1', 'Tbl2', 'fld1, fld2, fld3', 'fld4'fld5'fld6' (необязательно)

/****** Object:  StoredProcedure [dbo].[ps_TableGap]    Script Date: 10/03/2013 16:03:44 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

-- =============================================
-- Author:       Arnaud ALLAVENA
-- Create date: 03.10.2013
-- Description: Compare tables
-- =============================================
create PROCEDURE [dbo].[ps_TableGap]
    -- Add the parameters for the stored procedure here
    @Tbl1 as varchar(100),@Tbl2 as varchar(100),@Fld1 as varchar(1000), @Fld2 as varchar(1000)= ''
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.

    SET NOCOUNT ON;
--Variables
--@Tbl1 = table 1
--@Tbl2 = table 2
--@Fld1 = Fields to compare from table 1
--@Fld2 Fields to compare from table 2
Declare @SQL varchar(8000)= '' --SQL statements
Declare @nLoop int = 1 --loop counter
Declare @Pk varchar(1000)= '' --primary key(s) 
Declare @Pk1 varchar(1000)= '' --first field of primary key
declare @strTmp varchar(50) = '' --returns value in Pk determination
declare @FldTmp varchar (1000) = '' --temporarily fields for alias calculation

--If @Fld2 empty we take @Fld1
--fields rules: fields to be compare must be in same order and type - always returns Gap
If @Fld2 = '' Set @Fld2 = @Fld1

--Change @Fld2 with Alias prefix xxx become _xxx 
while charindex(',',@Fld2)>0
begin
    Set @FldTmp = @FldTmp + (select substring(@Fld2,1,charindex(',',@Fld2)-1) + ' as _' + substring(@Fld2,1,charindex(',',@Fld2)-1) + ',')
    Set @Fld2 = (select ltrim(right(@Fld2,len(@Fld2)-charindex(',',@Fld2))))
end
Set @FldTmp = @FldTmp + @Fld2 + ' as _' + @Fld2
Set @Fld2 = @FldTmp

--Determinate primary key jointure
--rule: same pk in both tables
Set @nLoop = 1
Set @SQL = 'Declare crsr cursor for select COLUMN_NAME from INFORMATION_SCHEMA.KEY_COLUMN_USAGE where TABLE_NAME = '''
 + @Tbl1 + ''' or TABLE_SCHEMA + ''.'' + TABLE_NAME = ''' + @Tbl1 +  ''' or TABLE_CATALOG + ''.'' + TABLE_SCHEMA + ''.'' + TABLE_NAME = ''' + @Tbl1 
 + ''' order by ORDINAL_POSITION'
exec(@SQL)
open crsr 
fetch next from crsr into @strTmp
while @@fetch_status = 0
begin 
    if @nLoop = 1 
    begin 
        Set @Pk = 's.' + @strTmp + ' = b._' + @strTmp
        Set @Pk1 = @strTmp
        set @nLoop = @nLoop + 1 
    end 
    Else
    Set @Pk = @Pk + ' and s.' + @strTmp + ' = b._' + @strTmp
fetch next from crsr into @strTmp 

end 
close crsr
deallocate crsr

--SQL statement build
set @SQL = 'select case when s.' + @Pk1 + ' is null then ''Del'' when b._' + @Pk1 + ' is null then ''Add'' else ''Gap'' end as TypErr, '''
set @SQL = @SQL + @Tbl1 +''' as Tbl1, s.*, ''' + @Tbl2 +''' as Tbl2 ,b.* from (Select ' + @Fld1 + ' from ' + @Tbl1
set @SQL = @SQL + ' EXCEPT SELECT ' + @Fld2 + ' from ' + @Tbl2 + ')s full join (Select ' + @Fld2 + ' from ' + @Tbl2 
set @SQL = @SQL + ' EXCEPT SELECT ' + @Fld1 + ' from ' + @Tbl1 +')b on '+ @Pk 

--Run SQL statement
Exec(@SQL)
END
0 голосов
/ 10 июля 2019

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

Шаг 1: - Выберите, какие все столбцы нам нужно сравнить из таблицы (T1) схемы (S)

     SELECT T1.col1,T1.col3,T1.col5 from S.T1

Шаг 2: - Используйте ключевое слово «Минус» для сравнения 2 таблиц.

Шаг 3: - Выберите, какие все столбцы нам нужно сравнить из таблицы (T2) схемы (S)

     SELECT T2.col1,T2.col3,T2.col5 from S.T1

КОНЕЦ результат: - ВЫБЕРИТЕ T1.col1, T1.col3, T1.col5 из S.T1 МИНУС ВЫБЕРИТЕ T2.col1, T2.col3, T2.col5 из S.T1;

Если запрос не возвращает строк, данные точно такие же.

0 голосов
/ 24 августа 2018

Большинство ответов, кажется, игнорируют проблему, поднятую Камилом.(Вот где таблицы содержат одинаковые строки, но в каждой таблице повторяются разные.) К сожалению, я не могу использовать его решение, потому что я в Oracle.Лучшее, что я смог придумать, это:

SELECT * FROM
   (
   SELECT column1, column2, ..., COUNT(*) AS the_count
   FROM tableA
   GROUP BY column1, column2, ...
   MINUS
   SELECT column1, column2, ..., COUNT(*) AS the_count
   FROM tableB
   GROUP BY column1, column2, ...
   )
UNION ALL
   (
   SELECT column1, column2, ..., COUNT(*) AS the_count
   FROM tableB
   GROUP BY column1, column2, ...
   MINUS
   SELECT column1, column2, ..., COUNT(*) AS the_count
   FROM tableA
   GROUP BY column1, column2, ...
   )
0 голосов
/ 31 июля 2018
SELECT * 
FROM TABLE A
WHERE NOT EXISTS (SELECT 'X' 
                  FROM  TABLE B 
                  WHERE B.KEYFIELD1 = A.KEYFIELD1 
                  AND   B.KEYFIELD2 = A.KEYFIELD2 
                  AND   B.KEYFIELD3 = A.KEYFIELD3)
;

'X' - любое значение.

Переключите таблицы, чтобы увидеть различные расхождения.

Не забудьте объединить ключевые поля в ваших таблицах.

Или просто используйте оператор МИНУС с двумя операторами выбора, однако МИНУС может работать только в Oracle.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...