J'ai 2 tables TableA
et TableB
qui ont le même format de colonne par exemple les deux tables TableA
et TableB
ont des colonnes
A B C D E F
où A et B sont les clés primaires.
Comment écrire SQL pour vérifier que si TableA
et TableB
qui ont les mêmes clés primaires contiennent exactement la même valeur dans toutes les colonnes.
Cela signifie que ces deux tables contiennent exactement les mêmes données.
tableA
a des lignes supplémentaires. Vous auriez besoin,(A EXCEPT B) INTERSECT (B EXCEPT A)
je suppose que ce serait beaucoup moins efficace qu'une jointure standard de tourbière.Utilisation des opérateurs relationnels:
SELECT * FROM TableA UNION SELECT * FROM TableB EXCEPT SELECT * FROM TableA INTERSECT SELECT * FROM TableB;
Changer
EXCEPT
àMINUS
pour Oracle.Point légèrement difficile: ce qui précède repose sur la priorité des opérateurs, qui, selon la norme SQL, dépend de l'implémentation, donc YMMV. Cela fonctionne pour SQL Server, pour lequel la priorité est:
INTERSECT
EXCEPT
etUNION
évalué de gauche à droite.la source
dietbuddha a une bonne réponse. Dans les cas où vous n'avez pas de MOINS ou D'EXCEPTION, une option est de faire une union entre les tables, regrouper avec toutes les colonnes et assurez-vous qu'il y en a deux de tout:
SELECT col1, col2, col3 FROM (SELECT * FROM tableA UNION ALL SELECT * FROM tableB) data GROUP BY col1, col2, col3 HAVING count(*)!=2
la source
DISTINCT
/GROUP BY
est suggéré pour les sous-requêtes dans l'union, pour s'assurer qu'il n'y a qu'un seul enregistrement par table. Sinon, TableA pourrait avoir 2 enregistrements et TableB pourrait avoir 0 et ne pas remplir la condition HAVING.SELECT c.ID FROM clients c WHERE EXISTS(SELECT c2.ID FROM clients2 c2 WHERE c2.ID = c.ID);
Renvoie tous les ID qui sont les MÊMES dans les deux tables. Pour obtenir les différences, remplacez EXISTS par NOT EXISTS.
la source
Prenant le script à partir d'un jour, je l'ai modifié pour montrer également de quelle table provient chaque entrée.
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
la source
juste pour terminer, un processus stocké en utilisant la méthode except pour comparer 2 tables et donner le résultat dans la même table avec 3 états d'erreurs, ADD, DEL, GAP table doit avoir le même PK, vous déclarez les 2 tables et champs à comparer de 1 ou des deux
Utilisez simplement comme ceci ps_TableGap 'tbl1', 'Tbl2', 'fld1, fld2, fld3', 'fld4'fld5'fld6' (facultatif)
/****** 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
la source
Source: Utilisez NATURAL FULL JOIN pour comparer deux tables en SQL par Lukas Eder
Approche intelligente d'utilisation
NATURAL FULL JOIN
pour détecter les mêmes / différentes lignes entre deux tables.Exemple 1 - indicateur d'état:
SELECT t1.*, t2.*, CASE WHEN t1 IS NULL OR t2 IS NULL THEN 'Not equal' ELSE 'Equal' END FROM t1 NATURAL FULL JOIN t2;
Exemple 2 - Filtrage des lignes
SELECT * FROM (SELECT 't1' AS t1, t1.* FROM t1) t1 NATURAL FULL JOIN (SELECT 't2' AS t2, t2.* FROM t2) t2 WHERE t1 IS NULL OR t2 IS NULL -- show differences --WHERE t1 IS NOT NULL AND t2 IS NOT NULL -- show the same
démo db <> fiddle
la source
Amélioration de la réponse de Dietbuddha ...
select * from ( select * from tableA minus select * from tableB ) union all select * from ( select * from tableB minus select * from tableA )
la source
Vous pouvez trouver les différences de 2 tables en utilisant la combinaison de insérer tout et de jointure externe complète dans Oracle. Dans SQL, vous pouvez extraire les différences via une jointure externe complète, mais il semble que insérer tout / d'abord n'existe pas dans SQL! Par conséquent, vous devez utiliser la requête suivante à la place:
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
Bien que l'utilisation de la clause 'OR' dans la clause where ne soit pas recommandée et qu'elle génère généralement des performances inférieures, vous pouvez toujours utiliser la requête ci-dessus si vos tables ne sont pas massives. S'il y a un résultat pour la requête ci-dessus, ce sont exactement les différences de 2 tables basées sur la comparaison des champs 1,2,3,4. Pour améliorer les performances de la requête, vous pouvez également la filtrer par date (vérifiez la partie commentée)
la source
SELECT unnest(ARRAY[1,2,2,3,3]) EXCEPT SELECT unnest(ARRAY[1,1,2,3,3]) UNION SELECT unnest(ARRAY[1,1,2,3,3]) EXCEPT SELECT unnest(ARRAY[1,2,2,3,3])
Le résultat est nul, mais les sources sont différentes!
Mais:
( SELECT unnest(ARRAY[1,2,2,3]) EXCEPT ALL SELECT unnest(ARRAY[2,1,2,3]) ) UNION ( SELECT unnest(ARRAY[2,1,2,3]) EXCEPT ALL SELECT unnest(ARRAY[1,2,2,3]) )
travaux.
la source
J'ai eu ce même problème dans SQL Server et j'ai écrit ce script T-SQL pour automatiser le processus (en fait, c'est la version édulcorée, la mienne a écrit tous les diff dans une seule table pour faciliter les rapports).
Mettez à jour «MyTable» et «MyOtherTable» avec les noms des tables que vous souhaitez comparer.
DECLARE @ColName varchar(100) DECLARE @Table1 varchar(100) = 'MyTable' DECLARE @Table2 varchar(100) = 'MyOtherTable' IF (OBJECT_ID('tempdb..#col') IS NOT NULL) DROP TABLE #col SELECT IDENTITY(INT, 1, 1) RowNum , c.name INTO #col FROM SYS.Objects o JOIN SYS.columns c on o.object_id = c.object_id WHERE o.name = @Table1 AND NOT c.Name IN ('List','Columns','YouWantToIgnore') DECLARE @Counter INT = (SELECT MAX(RowNum) FROM #col) WHILE @Counter > 0 BEGIN SET @ColName = (SELECT name FROM #Col WHERE RowNum= @Counter) EXEC ('SELECT t1.Identifier ,t1.'+@ColName+' AS '+@Table1+@ColName+' ,t2.'+@ColName+' AS '+@Table2+@ColName+' FROM '+@Table1+' t1 LEFT JOIN '+@Table2+' t2 ON t1.Identifier = t2.Identifier WHERE t1.'+@ColName+' <> t2.'+@ColName) SET @Counter = @Counter - 1 END
la source
J'ai écrit ceci pour comparer les résultats d'une vue assez désagréable que j'ai portée d'Oracle vers SQL Server. Il crée une paire de tables temporaires, #DataVariances et #SchemaVariances, avec des différences dans (vous l'avez deviné) les données dans les tables et le schéma des tables elles-mêmes.
Il faut que les deux tables aient une clé primaire, mais vous pouvez la déposer dans tempdb avec une colonne d'identité si les tables source n'en ont pas.
declare @TableA_ThreePartName nvarchar(max) = '' declare @TableB_ThreePartName nvarchar(max) = '' declare @KeyName nvarchar(max) = '' /*********************************************************************************************** Script to compare two tables and return differneces in schema and data. Author: Devin Lamothe 2017-08-11 ***********************************************************************************************/ set nocount on -- Split three part name into database/schema/table declare @Database_A nvarchar(max) = ( select left(@TableA_ThreePartName,charindex('.',@TableA_ThreePartName) - 1)) declare @Table_A nvarchar(max) = ( select right(@TableA_ThreePartName,len(@TableA_ThreePartName) - charindex('.',@TableA_ThreePartName,len(@Database_A) + 2))) declare @Schema_A nvarchar(max) = ( select replace(replace(@TableA_ThreePartName,@Database_A + '.',''),'.' + @Table_A,'')) declare @Database_B nvarchar(max) = ( select left(@TableB_ThreePartName,charindex('.',@TableB_ThreePartName) - 1)) declare @Table_B nvarchar(max) = ( select right(@TableB_ThreePartName,len(@TableB_ThreePartName) - charindex('.',@TableB_ThreePartName,len(@Database_B) + 2))) declare @Schema_B nvarchar(max) = ( select replace(replace(@TableB_ThreePartName,@Database_B + '.',''),'.' + @Table_B,'')) -- Get schema for both tables declare @GetTableADetails nvarchar(max) = ' use [' + @Database_A +'] select COLUMN_NAME , DATA_TYPE from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = ''' + @Table_A + ''' and TABLE_SCHEMA = ''' + @Schema_A + ''' ' create table #Table_A_Details ( ColumnName nvarchar(max) , DataType nvarchar(max) ) insert into #Table_A_Details exec (@GetTableADetails) declare @GetTableBDetails nvarchar(max) = ' use [' + @Database_B +'] select COLUMN_NAME , DATA_TYPE from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = ''' + @Table_B + ''' and TABLE_SCHEMA = ''' + @Schema_B + ''' ' create table #Table_B_Details ( ColumnName nvarchar(max) , DataType nvarchar(max) ) insert into #Table_B_Details exec (@GetTableBDetails) -- Get differences in table schema select ROW_NUMBER() over (order by a.ColumnName , b.ColumnName) as RowKey , a.ColumnName as A_ColumnName , a.DataType as A_DataType , b.ColumnName as B_ColumnName , b.DataType as B_DataType into #FieldList from #Table_A_Details a full outer join #Table_B_Details b on a.ColumnName = b.ColumnName where a.ColumnName is null or b.ColumnName is null or a.DataType <> b.DataType drop table #Table_A_Details drop table #Table_B_Details select coalesce(A_ColumnName,B_ColumnName) as ColumnName , A_DataType , B_DataType into #SchemaVariances from #FieldList -- Get differences in table data declare @LastColumn int = (select max(RowKey) from #FieldList) declare @RowNumber int = 1 declare @ThisField nvarchar(max) declare @TestSql nvarchar(max) create table #DataVariances ( TableKey nvarchar(max) , FieldName nvarchar(max) , TableA_Value nvarchar(max) , TableB_Value nvarchar(max) ) delete from #FieldList where A_DataType in ('varbinary','image') or B_DataType in ('varbinary','image') while @RowNumber <= @LastColumn begin set @TestSql = ' select coalesce(a.[' + @KeyName + '],b.[' + @KeyName + ']) as TableKey , ''' + @ThisField + ''' as FieldName , a.[' + @ThisField + '] as [TableA_Value] , b.[' + @ThisField + '] as [TableB_Value] from [' + @Database_A + '].[' + @Schema_A + '].[' + @Table_A + '] a inner join [' + @Database_B + '].[' + @Schema_B + '].[' + @Table_B + '] b on a.[' + @KeyName + '] = b.[' + @KeyName + '] where ltrim(rtrim(a.[' + @ThisField + '])) <> ltrim(rtrim(b.[' + @ThisField + '])) or (a.[' + @ThisField + '] is null and b.[' + @ThisField + '] is not null) or (a.[' + @ThisField + '] is not null and b.[' + @ThisField + '] is null) ' insert into #DataVariances exec (@TestSql) set @RowNumber = @RowNumber + 1 set @ThisField = (select coalesce(A_ColumnName,B_ColumnName) from #FieldList a where RowKey = @RowNumber) end drop table #FieldList print 'Query complete. Select from #DataVariances to verify data integrity or #SchemaVariances to verify schemas match. Data types varbinary and image are not checked.'
la source
La plupart des réponses semblent ignorer la question soulevée par Kamil. (C'est là que les tables contiennent des lignes identiques, mais des lignes différentes sont répétées dans chaque table.) Malheureusement, je ne peux pas utiliser sa solution, car je suis dans Oracle. Le mieux que j'ai pu trouver est:
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, ... )
la source
Pour comparer T1 (PK, A, B) et T2 (PK, A, B).
Commencez par comparer les ensembles de clés primaires pour rechercher les valeurs de clé manquantes de chaque côté:
SELECT T1.*, T2.* FROM T1 FULL OUTER JOIN T2 ON T1.PK=T2.PK WHERE T1.PK IS NULL OR T2.PK IS NULL;
Ensuite, listez toutes les incohérences de valeurs:
SELECT T1.PK, 'A' AS columnName, T1.A AS leftValue, T2.A AS rightValue FROM T1 JOIN T2 ON T1.PK=T2.PK WHERE COALESCE(T1.A,0) != COALESCE(T2.A,0) UNION ALL SELECT T1.PK, 'B' AS columnName, T1.B AS leftValue, T2.B AS rightValue FROM T1 JOIN T2 ON T1.PK=T2.PK WHERE COALESCE(T1.B,0) != COALESCE(T2.B,0)
A et B doivent être du même type. Vous pouvez utiliser INFORMATION SCHEMA pour générer le SELECT. N'oubliez pas le COALESCE pour inclure également les résultats IS NULL. Vous pouvez également utiliser FULL OUTER JOIN et COALESCE (T1.PK, 0) = COALESCE (T2.PK, 0).
Par exemple pour les colonnes de type varchar:
SELECT concat('SELECT T1.PK, ''', COLUMN_NAME, ''' AS columnName, T1.', COLUMN_NAME, ' AS leftValue, T2.', COLUMN_NAME, ' AS rightValue FROM T1 JOIN T2 ON T1.PK=T2.PK WHERE COALESCE(T1.',COLUMN_NAME, ',0)!=COALESCE(T2.', COLUMN_NAME, ',0)') FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='T1' AND DATA_TYPE IN ('nvarchar','varchar');
la source
Nous pouvons comparer les données de deux tables de tables DB2 à l'aide de la requête simple ci-dessous,
Étape 1: - Sélectionnez toutes les colonnes à comparer à partir du tableau (T1) du schéma (S)
SELECT T1.col1,T1.col3,T1.col5 from S.T1
Étape 2: - Utilisez le mot-clé «Moins» pour comparer 2 tableaux.
Étape 3: - Sélectionnez toutes les colonnes à comparer à partir du tableau (T2) du schéma (S)
SELECT T2.col1,T2.col3,T2.col5 from S.T1
Résultat FIN:
SELECT T1.col1,T1.col3,T1.col5 from S.T1 MINUS SELECT T2.col1,T2.col3,T2.col5 from S.T1;
Si la requête ne renvoie aucune ligne, les données sont exactement les mêmes.
la source
Dans MySQL, où "moins" n'est pas pris en charge et compte tenu des performances, il s'agit d'un rapide
query: SELECT t1.id, t1.id FROM t1 inner join t2 using (id) where concat(t1.C, t1.D, ...)<>concat(t2.C, t2.D, ...)
la source
Une requête alternative et améliorée basée sur la réponse de dietbuddha & IanMc. La requête comprend une description pour montrer utilement où les lignes existent et sont manquantes. (NB: pour SQL Server )
( select 'InTableA_NoMatchInTableB' as Msg, * from tableA except select 'InTableA_NoMatchInTableB' , * from tableB ) union all ( select 'InTableB_NoMatchInTableA' as Msg, * from tableB except select 'InTableB_NNoMatchInTableA' ,* from tableA )
la source
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» est une valeur quelconque.
Changez de tableau pour voir les différents écarts.
Assurez-vous de joindre les champs clés de vos tables.
Ou utilisez simplement l'opérateur MINUS avec 2 instructions select, cependant, MINUS ne peut fonctionner que dans Oracle.
la source