2010-08-05 13 views
2

J'ai 2 bases de données qui ont la même structure, mais des données différentes. Les deux sont SQL 2005.Recherche de correspondances uniques dans deux bases de données distinctes

J'essaie de trouver laquelle des personnes dans la base de données A, existe dans la base de données B. Ma meilleure occasion pour le match est de faire correspondre sur FirstName et LastName.

Je veux seulement ramener une liste de:

DatabaseA.Person DatabaseB.Person

Où: 1. Je veux que tous les enregistrements de DatabaseA, même s'il n'y a pas une correspondance dans la base de données B. 2. Je ne veux que des enregistrements de DatabaseB où FirstName/LastName correspondent à un seul enregistrement dans DatabaseB.

J'ai écrit une requête, où je grouper par, mais comme j'ai besoin de voir plus de données que FirstName et LastName, je ne peux pas le ramener sans le grouper - ce qui me donne beaucoup de doublons. Quel type de requête devrais-je utiliser? Ai-je besoin d'utiliser un curseur?

Voici ma requête maintenant, quel genre de travaux - sauf que je reçois des résultats pour les doublons dans DatabaseB et tout ce que je veux savoir sur la base de données B est lorsque FirstName/LastName correspond à un enregistrement distinct et aucun autre. Mon objectif est d'obtenir une liste de personnes que je connais sont la même personne dans 2 bases de données afin que je puisse construire une liste de dictionnaire de mappages de code de département entre les employés.

select 
count(DatabaseAEmployee.id) as matchcount 
, DatabaseAPerson.id as DatabaseAPersonid 
, DatabaseAEmployee.DeptCode DatabaseADeptCode 
, DatabaseAPerson.firstname as DatabaseAfirst 
, DatabaseAPerson.lastname as DatabaseAlast 
, DatabaseBPerson.id as DatabaseBPersonid 
, DatabaseBEmployee.DeptCode as DatabaseBDeptCode 
, DatabaseBPerson.firstname as DatabaseBfirst 
, DatabaseBPerson.lastname as DatabaseBlast 
, DatabaseAPerson.ssn as DatabaseAssn 
, DatabaseBPerson.ssn as DatabaseBssn 
, DatabaseAPerson.dateofbirth as DatabaseAdob 
, DatabaseBPerson.dateofbirth as DatabaseBdob 

FROM [DatabaseA].[dbo].Employee DatabaseAEmployee 
LEFT OUTER JOIN [DatabaseA].[dbo].Person DatabaseAPerson 
ON DatabaseAPerson.id = DatabaseAEmployee.id 
LEFT OUTER JOIN [DatabaseB].[dbo].Person DatabaseBPerson 
ON 
DatabaseAPerson.firstname = DatabaseBPerson.firstname 
AND 
DatabaseAPerson.lastname = DatabaseBPerson.lastname 
LEFT OUTER JOIN [DatabaseB].[dbo].Employee DatabaseBEmployee 
on DatabaseBEmployee.id = DatabaseBPerson.id 
group by 
DatabaseAPerson.firstname 
, DatabaseAPerson.lastname 
, DatabaseAPerson.id 
, DatabaseAEmployee.DeptCode 
, DatabaseBPerson.id 
, DatabaseBEmployee.DeptCode 
, DatabaseBPerson.firstname 
, DatabaseBPerson.lastname 
, DatabaseBPerson.ssn 
, DatabaseAPerson.ssn 
, DatabaseBPerson.dateofbirth 
, DatabaseAPerson.dateofbirth 

Voici ce que je suis en train, mais je suis en train de doublons sur le côté gauche:

with UniqueMatchedPersons (Id, FirstName, LastName) 
as (
select 
    p2.ID, p2.FirstName, p2.LastName 
from 
    [DatabaseA].[dbo].[Employee] p1 
INNER JOIN [DatabaseA].[dbo].[Person] p2 on p1.id = p2.id 
    inner join [DatabaseB].[dbo].[Person] p3 
     on p2.FirstName = p3.FirstName and p2.LastName = p3.LastName 
INNER JOIN [DatabaseB].[dbo].[Employee] p4 
on p3.id = p4.id 

group by p2.ID, p2.FirstName, p2.LastName 
having count(p2.ID) = 1 

) 

select p1.*, p2.* 
from DatabaseA.dbo.Person p1 
inner join UniqueMatchedPersons on p1.ID = UniqueMatchedPersons.ID 
left outer join DatabaseB.dbo.Person p2 
    on p1.FirstName = p2.FirstName and p1.LastName = p2.LastName 
+2

Pour quelle base de données? S'il vous plaît inclure la version. Il semble que vous voulez 'INTERSECT' ... –

+0

également inclure la structure de la table et l'exemple de données, afin que nous puissions vous aider plus facilement –

Répondre

2

Essayez ceci:

SELECT id,FirstName,Lastname 
FROM dba.Persons 
UNION 
SELECT b.id,b.FirstName,b.LastName 
FROM dbb.Persons as b 
INNER JOIN dba.Persons as a 
ON b.FirstName = a.FirstName AND b.LastName = a.LastName 

Si vous voulez obtenir tous de A et seulement ceux de B qui n'ont pas de correspondance (ce qui aurait plus de sens pour moi) j'utiliserais ceci:

SELECT id,FirstName,Lastname 
FROM dba.Persons 
UNION 
SELECT b.id,b.FirstName,b.LastName 
FROM dbb.Persons as b 
LEFT OUTER JOIN dba.Persons as a 
ON b.FirstName = a.FirstName AND b.LastName = a.LastName 
WHERE a.id is null 
2

Essayez quelque chose comme:

Select dta.LastName, dta.FirstName, dta.[otherColumns] dtb.LastName, dtb.FirstName 
    dtb.[otherColumns] 
From [databaseA].[table] as dta 
LEFT OUTER JOIN [databaseB].[table] as dtb 
    on dta.Lastname = dtb.LastName and dta.FirstName = dtb.FirstName 

Cela devrait vous faire: 1) tout le monde dans le tableau A, et 2) tout le monde dans le tableau B qui est a un match Nom/Prénom dans le tableau A.

2

Works lorsque SQL Server (au moins il se doit)

SELECT 
    A.* 
    , B.* 
FROM 
    DatabaseA.dbo.Person A 
    LEFT JOIN DatabaseB.dbo.Person B 
     ON A.FirstName = B.FirstName AND A.LastName = B.LastName 

Edit: vous mentionnez que vous recevez des doublons de DatabaseB où vous avez besoin du match sur la première et lastname. Mais vous demandez également d'autres données (puis prénom/nom) c'est le problème. Si vous avez des données distinctes, vous ne demandez que ces données.

2

En utilisant transact-SQL, la requête non testée suivante devrait vous permettre de voir les matchs uniques seulement:

select 
    p1.ID, p1.FirstName, p1.LastName 
from 
    [DatabaseA].[dbo].[Persons] p1 
    left outer join [DatabaseB].[dbo].[Persons] p2 
     on p1.FirstName = p2.FirstName and p1.LastName = p2.LastName 

group by p1.ID, p1.FirstName, p2.LastName 

having count(p1.ID) = 1 

Si vous utilisez Sql Server, cela peut alors être encapsulé dans une expression de table commune, à laquelle vous pouvez effectuer une jointure.

with UniqueMatchedPersons (Id, FirstName, LastName) 
as (
    --query in previous code snippet 
) 
select persons.* 
from Persons 
inner join UniqueMatchedPersons on Persons.ID = UniqueMatchedPersons.ID 

Mise à jour:

Si vous souhaitez sélectionner les champs des deux tables, vous pouvez simplement respécifier la condition de jointure originale qui a évalué le nom correspondant avant; En effet, les correspondances dupliquées sur le côté gauche de la jointure ont été filtrées par la condition agrégée having.

Modification de la partie select de l'extrait ci-dessus pour lire ce qui suit vous permettra de sélectionner les champs de chaque côté de la jointure:

select p1.*, p2.* 
from [DatabaseA].[dbo].[Persons] p1 
inner join UniqueMatchedPersons on p1.ID = UniqueMatchedPersons.ID 
left outer join [DatabaseB].[dbo].[Persons] p2 
    on p1.FirstName = p2.FirstName and p1.LastName = p2.LastName 

Mise à jour 2:

Pour filtrer les doublons sur le côté gauche (ce qui provoquera également des doublons sur la droite), vous devrez supprimer le groupement sur [DatabaseA].[dbo].[Persons].[ID]. Lorsque je parle de doublons, je veux dire des noms dans les rangées adjacentes identiques en termes de caractères et de remplissage. Si vous avez des variations diacritiques du prénom et du nom, alors les résultats de la comparaison des noms seront soumis au classement de la base de données (à moins que vous n'excluiez explicitement un classement sur une expression de jointure). De même, si vous avez des variations d'espacement, de remplissage ou de ponctuation entre les noms, vous devrez peut-être envisager une approche différente de celle d'un opérateur d'égalité directe pour la correspondance des noms.

les opérations suivantes:

with UniqueMatchedPersons (FirstName, LastName) 
as (
select 
    p1.FirstName, p1.LastName 
from 
    [DatabaseA].[dbo].[Person] p1 
    left outer join [DatabaseB].[dbo].[Person] p2 
     on p2.FirstName = p3.FirstName and p2.LastName = p3.LastName 

group by p1.FirstName, p1.LastName 
having count(p1.FirstName) = 1 
) 

select p1.*, p2.*, e1.*, e2.* 
from [DatabaseA].[dbo].[Person] p1 
inner join UniqueMatchedPersons ump 
     on p1.FirstName = ump.FirstName and p1.LastName = ump.LastName 
left outer join [DatabaseB].[dbo].[Person] p2 
     on p1.FirstName = p2.FirstName and p1.LastName = p2.LastName 
inner join [DatabaseA].[dbo].[Employee] e1 on p1.ID = e1.ID 
inner join [DatabaseB].[dbo].[Employee] e2 on e2.ID = p2.ID 

order by p1.id asc 
+0

Merci beaucoup pour tous les détails. J'essaie votre deuxième requête (j'ai mis à jour ma question pour la contenir). Mais je reçois encore des doublons sur le côté gauche et à droite. – user53885

+0

On dirait que vous avez des doublons dans la table '[DatabaseA]. [Dbo]. [Persons]', où plusieurs personnes partagent le même prénom et le même nom mais ont des ID différents. Je vais mettre à jour ma réponse. – Rabid

Questions connexes