2010-10-20 55 views
4

我试图将2个数据库合并在一起,并且这是它的一部分。以不同顺序在多个列中查找匹配

我改变了主题让它更容易理解 - 我无法改变这个模式,这正是我正在使用的模式。

我在下面列我的两个源和目标数据库的表:

Car 
CarType1 
CarType2 
CarType3 
CarType4 

我想写一个查询,会告诉我在目标数据库中,这行具有之间的相同汽车2个数据库,但不同的CarTypes。我需要的是对不同行的计数。

我用英语写的查询应该是: 将我带回的行数与Car相同,两个系统之间的CarType不匹配。 CarType是否在两者之间的CarType字段中并不重要,只是所有值是否都包含在4个字段之一中。

所以,如果在我的源数据库中该行:

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

而且在我的目标数据库中,我有这样一行:

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

这只能算作一个不匹配,因为它是一个野马并且因为CarType字段的聚合是不同的。这些值在什么顺序并不重要。

我该如何写这个查询?我无法理解它。

+1

有谁强迫你给我们这种模式应该切断他们的双手。 – 2010-10-20 22:02:49

+0

:“}它完全令我困惑,但我无法改变它..我可以选择所有东西放到不同的模式中以生成我需要的这些报告。 – user53885 2010-10-20 22:04:47

回答

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 
    ) 
) 

或者稍短的版本

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

这将返回类型为XML。您对我的解决方案有何想法?我尝试了你的CTE,他们返回相同的结果 – 2010-10-20 22:26:43

+0

@Abe - 现在摆脱了XML连接步骤 – 2010-10-20 23:12:48

+0

似乎有点清洁,仍然试图弄清楚'SELECT COUNT'部分是如何工作的... – 2010-10-21 01:28:48

1

试试这个,让我知道,如果它的工作原理:

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) 

注:

你将不得不ISNULL s添加到这个包含或排除列是否为空。

要排除:

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

要包括:

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

注意:使用IN()是一种在不可预测的有序项目集合之间进行匹配的简单方法。 COALESCE()将防止在处理包含NULL的列时遇到任何失败或不一致。如果行相同,则LEN()总数的比较应匹配。 – 2010-10-21 01:51:39

+0

应该合并(c3。coalesece(c1。?如果不是什么c3。?谢谢 – user53885 2010-10-21 04:15:44

+0

您是对的,我已更正查询。 – 2010-10-21 05:39:20