SQL Help:查找导致不匹配的列

时间:2010-01-23 00:05:42

标签: sql tsql

下面的查询根据4列中的值选择table_1中不存在于table_2中的行。不匹配可能是由于一列或多列。

我想通过显示列名称或其值来扩展查询以告诉我哪些列具有不匹配的值。我可以在游标中执行此操作,但如果可能,则更喜欢在基于集合的操作中执行此操作。

SELECT  i.agent ,
        i.agency ,
        i.customer ,
        i.Company
FROM    table_1 AS i
WHERE   NOT EXISTS ( SELECT p.agent ,
                            p.agency ,
                            p.customer ,
                            p.Company
                     FROM   table_2 AS p
                     WHERE  i.Agent = p.Agent
                            AND i.agency = p.Agency
                            AND i.customer = p.customer
                            AND i.Company = p.Company )

更新 我想这需要更多的改进。让我们补充说,4列中的3列需要匹配。

3 个答案:

答案 0 :(得分:2)

如果您需要某些列执行匹配,或者至少从某些期望 匹配的列开始,您可以大大简化此问题。换句话说,不要将其视为不匹配的问题,而是将其重新定义为部分匹配问题。

假设您希望agentagency匹配,但customercompany可能不匹配。这不是太难:

SELECT
    i.agent, i.agency, i.customer, i.company, p.customer, p.company,
    CASE
        WHEN i.customer = p.Customer THEN 'Y'
        ELSE 'N'
    END AS matchescustomer,
    CASE
        WHEN i.company = p.Company THEN 'Y'
        ELSE 'N'
    END AS matchescompany
FROM table1 i
INNER JOIN table2 p
    ON p.agent = i.agent
    AND p.agency = i.agency

如果要检查其他部分匹配,只需重新排序列。加入agentagency或其他任何内容,而不是加入agentcustomer

如果您只想要几种不同类型的部分匹配,则可以编写一些与上述类似的不同查询,并将其与UNION(或UNION ALL放在一起,如果不这样做介意重复)。换句话说:

SELECT (columns)
FROM table1 i INNER JOIN table2 p
    ON p.agent = i.agent AND p.agency = i.agency
UNION
SELECT (columns)
FROM table1 i INNER JOIN table2 p
    ON p.agent = i.agent AND p.customer = i.customer

现在,如果您希望得到所有可能的不匹配,那么这很快就会失去控制,因此您可能希望采用更具启发性的方法,并搜索部分匹配匹配至少一定数量的列(比如3)。然后,您可以将讨厌的内容限制为最多必须比较的列数:

;WITH PartialMatches_CTE AS
(
    SELECT i.agent AS iagent, p.agent AS pagent, ... (etc.)
    FROM table1 i INNER JOIN table2 p ON p.agent = i.agent
    UNION ALL
    SELECT (...) FROM table1 INNER JOIN table2 ON p.agency = i.agency
    UNION ALL
    SELECT (...) FROM table1 INNER JOIN table2 ON p.company = i.company
    ... and so on
),
ResolvedMatches_CTE AS
(
    SELECT DISTINCT
        iagent, pagent, iagency, pagency, ...,
        CASE WHEN pagent = iagent THEN 'Y' ELSE 'N' END AS agentmatch,
        CASE WHEN pagency = iagency THEN 'Y' ELSE 'N' END AS agencymatch,
        ...,
        (CASE WHEN pagent = iagent THEN 1 ELSE 0 END +
         CASE WHEN pagency = iagency THEN 1 ELSE 0 END +
         ...) AS MatchCount
    FROM PartialMatches_CTE
)
SELECT *
FROM ResolvedMatches_CTE
WHERE MatchCount >= 3

现在,说了这么多,有一件事我想知道......

这两个数据表不是顺序相关的,是吗?如表1所示,table1中的第3行始终映射到表2中的第3行,但可能与所有列不匹配?这是一个黑暗的镜头,但如果确实如此,那么我们可以使这个方式更简单。否则,这里的最后一个查询可能应该做你想要的,而不会成为太多非常难以维护的混乱。

请注意,所有这些查询的性能可能会很糟糕。希望您的数据集不会太大。 AFAIK没有简单的方法来真正优化这种事情。

答案 1 :(得分:1)

正如其他人所说,这个问题需要更多地定义。

假设您在表1中有这些对象:

  1. 大,红,甜苹果
  2. 小,绿,酸苹果
  3. 中等,橙色,甜桃
  4. 中等,橙色,酸性橘子
  5. 表2中的这些对象:

    1. 小,红,甜李子
    2. 大,红,甜苹果
    3. 小,绿,酸苹果
    4. 小,橙,甜橘子
    5. 现在,让我们通过表1:

      1. 大,红,甜苹果与表2中的第2项相符
      2. 小,绿,酸苹果没有匹配 - 哪个列不匹配?
        • 表2,第1项 - 大小,颜色,味道和水果不匹配
        • 表2,第1项 - 尺寸,颜色和味道不匹配
        • ...
        • ...
      3. (也没有匹配)
        • ...
        • ...
        • ...
        • ...
      4. (也没有匹配)
        • ...
        • ...
        • ...
        • ...
      5. 正如您所看到的,这很快成为一个指数问题。每个列表中只有四个项目,您有12个不匹配的对列表列。如果您有100,000件商品和10,000件不匹配商品,那么您必须列出1亿双商品。

        如果您重新定义查询以便它仅列出一个属性(列)上不同的项目,那么它可能会更加可行。像这样:

        -- warning untested code --
        
                 SELECT 'agent' AS MismatchedColumn ,
                        p.agent AS MismatchedValue ,
                        i.agent ,
                        i.agency ,
                        i.customer , 
                        i.company
                   FROM table_1 AS i
        LEFT OUTER JOIN table_2 AS p
                     ON i.agent != p.agent
                        AND i.agency = p.agency
                        AND i.customer = p.customer
                        AND i.company = p.company
                  UNION
                 SELECT 'agency' AS MismatchedColumn ,
                        p.agency AS MismatchedValue ,
                        i.agent ,
                        i.agency ,
                        i.customer ,
                        i.company
                   FROM table_1 AS i
        LEFT OUTER JOIN table_2 AS p
                     ON i.agent = p.agent
                        AND i.agency != p.agency
                        AND i.customer = p.customer
                        AND i.company = p.company
                  UNION
                 SELECT 'customer' AS MismatchedColumn ,
                        p.customer AS MismatchedValue ,
                        i.agent ,
                        i.agency ,
                        i.customer ,
                        i.company
                   FROM table_1 AS i
        LEFT OUTER JOIN table_2 AS p
                     ON i.agent = p.agent
                        AND i.agency = p.agency
                        AND i.customer != p.customer
                        AND i.company = p.company
                  UNION
                 SELECT 'company' AS MismatchedColumn ,
                        p.company AS MismatchedValue ,
                        i.agent ,
                        i.agency ,
                        i.customer ,
                        i.company
                   FROM table_1 AS i
        LEFT OUTER JOIN table_2 AS p
                     ON i.agent = p.agent
                        AND i.agency = p.agency
                        AND i.customer = p.customer
                        AND i.company != p.company
        

        我相信这会列出表1中除表2中所有列以外的所有记录。

答案 2 :(得分:0)

这个定义明确吗?如果p中存在[1,2,3,4]和[5,2,3,5],则i中的[1,2,3,5]与列的[1,2,3,4]不匹配d和列a的[5,2,3,5]不匹配。或者你会因为d和a而声称它是不匹配的?