2010-10-20 5 views
4

J'essaie de fusionner deux bases de données avec le même schéma ensemble, et c'est une partie de celui-ci.Trouver des correspondances dans plusieurs colonnes dans différents ordres

J'ai changé de sujet pour le rendre plus compréhensible - Je ne peux pas changer ce schéma, c'est juste ce que je travaille avec.

J'ai une table dans les deux mes sources et bases de données cibles avec les colonnes suivantes:

Car 
CarType1 
CarType2 
CarType3 
CarType4 

Je suis en train d'écrire une requête qui me dira dans la base de données cible, les lignes ont les mêmes voitures entre les 2 bases de données, mais différents CarTypes. Tout ce dont j'ai besoin, c'est d'un compte sur les lignes qui sont différentes.

Ma requête écrite en anglais serait: Ramenez-moi un nombre de lignes où la voiture est la même et les CarTypes entre les deux systèmes ne correspondent pas. Peu importe si le CarType est dans un champ CarType différent entre les deux, juste si toutes les valeurs sont contenues dans l'un des 4 champs ou non.

Donc, si dans ma base de données source cette ligne:

Car: Mustang 
CarType1: Fast 
CarType2: Convertible 
CarType3: null 
CarType4: null 

Et dans ma base de données cible J'ai cette ligne:

Car: Mustang 
CarType1: Fast 
CarType2: Convertible 
CarType3: Sports 
CarType4: null 

Cela comptera comme un non-match, car il est une Mustang et parce que l'ensemble des champs CarType est différent. Dans quel ordre les valeurs sont-elles, cela n'a pas d'importance pour cela.

Comment est-ce que j'écrirais cette requête? Je ne peux pas me faire comprendre.

+1

Qui vous oblige jamais à nous Ce schéma devrait avoir les mains coupées. –

+0

: "} cela me dérange complètement, mais je ne peux pas le changer .. Je peux peut-être tout sélectionner dans un schéma différent pour générer ces rapports dont j'ai besoin – user53885

Répondre

1
;WITH SourceT AS (
SELECT 'Toyota' AS Car, 'A' AS CarType1, 'B' AS CarType2, 'C' CarType3, 'D' CarType4 UNION ALL 
SELECT 'BMW' AS Car, 'A' AS CarType1, 'B' AS CarType2, 'C' CarType3, 'D' CarType4 UNION ALL 
SELECT 'Mustang' AS Car, 'Fast' AS CarType1, 'Convertible' AS CarType2, 'Sports' CarType3, NULL CarType4 
), 
TargetT AS (
SELECT 'Toyota' AS Car, 'D' AS CarType1, 'C' AS CarType2, 'B' CarType3, 'A' CarType4 UNION ALL 
SELECT 'BMW' AS Car, 'D' AS CarType1, 'C' AS CarType2, 'B' CarType3, 'A' CarType4 UNION ALL 
SELECT 'Mustang' AS Car, 'Fast' AS CarType1, 'Convertible' AS CarType2, NULL CarType3, NULL CarType4) 

SELECT * 
FROM SourceT s 
WHERE NOT EXISTS 
(
SELECT * 
FROM TargetT t 
WHERE s.Car = t.Car AND 0 = 
(SELECT COUNT(*) FROM 
    ((
     (SELECT s.CarType1 AS t UNION ALL 
     SELECT s.CarType2 AS t UNION ALL 
     SELECT s.CarType3 AS t UNION ALL 
     SELECT s.CarType4 AS t) 
    EXCEPT     
     (SELECT t.CarType1 AS t UNION ALL 
     SELECT t.CarType2 AS t UNION ALL 
     SELECT t.CarType3 AS t UNION ALL 
     SELECT t.CarType4 AS t) 
     ) 
    UNION ALL 
    (
     (SELECT t.CarType1 AS t UNION ALL 
     SELECT t.CarType2 AS t UNION ALL 
     SELECT t.CarType3 AS t UNION ALL 
     SELECT t.CarType4 AS t) 
    EXCEPT     
     (SELECT s.CarType1 AS t UNION ALL 
     SELECT s.CarType2 AS t UNION ALL 
     SELECT s.CarType3 AS t UNION ALL 
     SELECT s.CarType4 AS t) 
     )  
     ) T 
    ) 
) 

Ou un peu version plus courte

SELECT * 
FROM SourceT s 
WHERE NOT EXISTS 
(
SELECT * 
FROM TargetT t 
WHERE s.Car = t.Car AND 
(SELECT t FROM (SELECT s.CarType1 AS t UNION ALL 
       SELECT s.CarType2 AS t UNION ALL 
       SELECT s.CarType3 AS t UNION ALL 
       SELECT s.CarType4 AS t) D ORDER BY t FOR XML PATH(''))= 
(SELECT t FROM (SELECT t.CarType1 AS t UNION ALL 
       SELECT t.CarType2 AS t UNION ALL 
       SELECT t.CarType3 AS t UNION ALL 
       SELECT t.CarType4 AS t) D ORDER BY t FOR XML PATH('')) 
    ) 
+0

Cela renvoie les types comme XML .Quelles sont vos pensées sur ma solution? Je l'ai essayé avec vos CTEs et ils retournent la même chose –

+0

@Abe - Je me suis débarrassé de l'étape de concaténation XML maintenant –

+0

Cela semble un peu plus propre de cette façon, essayant toujours de comprendre comment fonctionne la section 'SELECT COUNT' ... –

1

Essayez et faites-moi savoir si cela fonctionne:

SELECT * FROM db1.dbo.Cars 
EXCEPT 
SELECT c1.* FROM db1.dbo.Cars as c1 
INNER JOIN db2.dbo.Cars as c2 
ON c1.Car = c2.Car 
     AND 
     --Check carType1 
     (c1.CarType1 = c2.CarType1 OR 
     c1.CarType1 = c2.CarType2 OR 
     c1.CarType1 = c2.CarType3 OR 
     c1.CarType1 = c2.CarType4) 
     AND 
     --Check carType2 
     (c1.CarType2 = c2.CarType1 OR 
     c1.CarType2 = c2.CarType2 OR 
     c1.CarType2 = c2.CarType3 OR 
     c1.CarType2 = c2.CarType4) 
     AND 
     --Check carType3 
     (c1.CarType3 = c2.CarType1 OR 
     c1.CarType3 = c2.CarType2 OR 
     c1.CarType3 = c2.CarType3 OR 
     c1.CarType3 = c2.CarType4) 
     AND 
     --Check carType4 
     (c1.CarType4 = c2.CarType1 OR 
     c1.CarType4 = c2.CarType2 OR 
     c1.CarType4 = c2.CarType3 OR 
     c1.CarType4 = c2.CarType4) 

REMARQUE:

Vous devez ajouter ISNULL s à ce à inclure ou exclure si une colonne est nulle.

Pour exclure:

ISNULL(c1.CarType4, -1) = ISNULL(c2.CarType4, -2) 

Pour inclure:

ISNULL(c1.CarType4, -1) = ISNULL(c2.CarType4, -1) 
1
SELECT c1.car 
FROM target.cars c1 
INNER JOIN source.cars c2 
ON c2.car = c1.car 
WHERE 
COALESCE(c1.cartype1, '') NOT IN 
('', c2.cartype1, c2.cartype2, c2.cartype3, c2.cartype4) 
OR 
COALESCE(c1.cartype2, '') NOT IN 
('', c2.cartype1, c2.cartype2, c2.cartype3, c2.cartype4) 
OR 
COALESCE(c1.cartype3, '') NOT IN 
('', c2.cartype1, c2.cartype2, c2.cartype3, c2.cartype4) 
OR 
COALESCE(c1.cartype4, '') NOT IN 
('', c2.cartype1, c2.cartype2, c2.cartype3, c2.cartype4) 
OR 
LEN(COALESCE(c1.cartype1, '') + COALESCE(c1.cartype2, '') + 
COALESCE(c1.cartype3, '') + COALESCE(c1.cartype4, '')) 
<> 
LEN(COALESCE(c2.cartype1, '') + COALESCE(c2.cartype2, '') + COALESCE(c2.cartype3, '') + 
COALESCE(c2.cartype4, '')) 
; 
+0

Remarques: L'utilisation de IN() est un moyen facile de faire correspondre un ensemble d'éléments classés de manière imprévisible. COALESCE() empêchera toute défaillance ou incohérence rencontrée lors du traitement des colonnes contenant NULL. La comparaison des totaux LEN() doit correspondre si les lignes sont identiques. –

+0

Devrait coalesce (c3 être coalesece (c1.? Si ce n'est pas c3.? Merci – user53885

+0

Vous avez raison, j'ai corrigé la requête. –

Questions connexes