275 votes

requête sql pour retourner les différences entre les deux tables

Je suis en train de comparer deux tableaux, SQL Server, afin de vérifier certaines données. Je veux retourner toutes les lignes des deux tables où les données sont soit dans l'un ou l'autre. En essence, j'en veux pour preuve toutes les divergences. J'ai besoin de vérifier trois morceaux de données en procédant de la sorte, FirstName, LastName et le Produit.

Je suis assez nouveau à SQL et il semble que beaucoup de solutions, je suis la recherche sont plus de compliquer les choses. Je n'ai pas à vous soucier de valeurs Null.

J'ai commencé par essayer quelque chose comme ceci:

SELECT DISTINCT [First Name], [Last Name], [Product Name] FROM [Temp Test Data]
WHERE ([First Name] NOT IN (SELECT [First Name] 
FROM [Real Data]))

Je vais avoir du mal à prendre ce plus loin cependant.

Merci!

EDIT:

Basé sur la réponse de @treaschf j'ai essayé d'utiliser une variante de la requête suivante:

SELECT td.[First Name], td.[Last Name], td.[Product Name]
FROM [Temp Test Data] td FULL OUTER JOIN [Data] AS d 
ON td.[First Name] = d.[First Name] AND td.[Last Name] = d.[Last Name] 
WHERE (d.[First Name] = NULL) AND (d.[Last Name] = NULL)

Mais je continue à recevoir 0 résultats arrière, quand je sais qu'il y a au moins 1 ligne de td qui n'est pas dans d.

EDIT:

Ok, je pense que j'ai tout compris. Au moins dans mes quelques minutes de test, il semble fonctionner assez bien.

SELECT [First Name], [Last Name]
FROM [Temp Test Data] AS td
WHERE (NOT EXISTS
        (SELECT [First Name], [Last Name]
         FROM [Data] AS d
         WHERE ([First Name] = td.[First Name]) OR ([Last Name] = td.[Last Name])))

C'est fondamentalement va me dire ce qui est dans mes données de test c'est pas dans mes données réelles. Ce qui est tout à fait acceptable pour ce que je dois faire.

338voto

erikkallen Points 16601
(   SELECT * FROM table1
    EXCEPT
    SELECT * FROM table2)  
UNION ALL
(   SELECT * FROM table2
    EXCEPT
    SELECT * FROM table1) 

289voto

treaschf Points 2112

SI vous avez des tables A et B, à la fois avec colum C, voici les enregistrements, qui sont présents dans le tableau A mais pas en B:

SELECT A.*
FROM A
    LEFT JOIN B ON (A.C = B.C)
WHERE B.C IS NULL

Pour obtenir toutes les différences avec une seule requête, un full join doit être utilisé, comme ceci:

SELECT A.*, B.*
FROM A
    FULL JOIN B ON (A.C = B.C)
WHERE A.C IS NULL OR B.C IS NULL

Ce que vous devez savoir en ce cas, c'est que lorsqu'un enregistrement peut être trouvé, en A, mais pas en B, que les colonnes qui viennent de l' B sera NULLE, et de même pour ceux qui sont présents en B et non pas en A, les colonnes de A sera nulle.

39voto

Maisie John Points 343

Je sais que cela peut ne pas être une réponse mais je suis d'accord avec @Randy Minder sur l'utilisation de l'outil tiers lorsque de plus en plus complexe la comparaison est nécessaire.

Ce cas spécifique ici est facile et, pour ce cas, de tels outils ne sont pas nécessaires, mais cela peut devenir complexe facilement si vous introduire plus de colonnes, des bases de données sur les deux serveurs, de plus en plus complexe de critères de comparaison.

Il y a un grand nombre de ces outils tels que ApexSQL Données Diff ou la Quête de Crapaud et vous pouvez toujours les utiliser en mode d'essai pour obtenir le travail fait.

8voto

Roman Pekar Points 31863

Si vous souhaitez obtenir dont les valeurs de colonne sont différents, vous pouvez utiliser de l'Entité-Attribut-Valeur de modèle:

declare @Data1 xml, @Data2 xml

select @Data1 = 
(
    select * 
    from (select * from Test1 except select * from Test2) as a
    for xml raw('Data')
)

select @Data2 = 
(
    select * 
    from (select * from Test2 except select * from Test1) as a
    for xml raw('Data')
)

;with CTE1 as (
    select
        T.C.value('../@ID', 'bigint') as ID,
        T.C.value('local-name(.)', 'nvarchar(128)') as Name,
        T.C.value('.', 'nvarchar(max)') as Value
    from @Data1.nodes('Data/@*') as T(C)    
), CTE2 as (
    select
        T.C.value('../@ID', 'bigint') as ID,
        T.C.value('local-name(.)', 'nvarchar(128)') as Name,
        T.C.value('.', 'nvarchar(max)') as Value
    from @Data2.nodes('Data/@*') as T(C)     
)
select
    isnull(C1.ID, C2.ID) as ID, isnull(C1.Name, C2.Name) as Name, C1.Value as Value1, C2.Value as Value2
from CTE1 as C1
    full outer join CTE2 as C2 on C2.ID = C1.ID and C2.Name = C1.Name
where
not
(
    C1.Value is null and C2.Value is null or
    C1.Value is not null and C2.Value is not null and C1.Value = C2.Value
)

SQL VIOLON EXEMPLE

2voto

Kango_V Points 1228

Essayez ceci :

SELECT 
    [First Name], [Last Name]
FROM 
    [Temp Test Data] AS td EXCEPTION JOIN [Data] AS d ON 
         (d.[First Name] = td.[First Name] OR d.[Last Name] = td.[Last Name])

Beaucoup plus simple à lire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X