2010-01-23 39 views
2

下面的查詢根據4列中的值選擇table_2中不存在的行。不匹配可能是由於一列或多列造成的。SQL幫助:查找哪些列導致不匹配

我想擴展查詢來告訴我哪些列有不匹配的值,或者通過顯示列名或其值。我可以在遊標中做到這一點,但如果可能的話,寧願在基於集合的操作中執行此操作。

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列需要匹配。

+1

@Tony_Henrich:我覺得這可能很難。你能否澄清一下:說一行(代理和代理)或者(客戶和公司)匹配 - 你想看什麼? – 2010-01-23 00:13:34

+0

如果代理和代理商匹配,我想查看'客戶,公司'或他們的價值。 – 2010-01-23 00:32:33

+0

我還是不明白......你能解釋一下,你想像一個5歲的孩子一樣完成什麼?如果不是在查詢方面,但在信息方面更好。 – jachguate 2010-01-23 01:23:13

回答

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)。然後,你可以最多限制obnoxiousness到的列數,你必須比較:

;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 

現在,說了這麼多,有一兩件事我不知道......

這兩個數據表不是,偶然的,依次相關的,是嗎?如中所示,table1中的第3行總是映射到表2中的第3行,但可能不匹配所有列?這是在黑暗中拍攝的,但如果確實如此,那麼我們可以簡化這種方式。否則,這裏的最後一個查詢應該可以做你想要的,而不會變成大部分不可維護的混亂。

請注意,對於所有這些查詢,性能可能會很差。希望你的數據集不太大。 AFAIK沒有簡單的方法來真正優化這種事情。

+0

+1這肯定比我的解決方案更靈活。雖然有點難纏我的頭。我猜'PartialMatches'列出了一列或多列上匹配的任何東西,然後'ResolvedMatches'表示每列是否匹配(Y或N)並且還計算匹配的數量。 'SELECT DISTINCT'擺脫所有重複。一個問題:如果你在第一個CTE而不是第二個CTE上選擇了「SELECT DISTINCT」,會發生什麼? – devuxer 2010-01-23 01:42:37

+0

@DanM:CTE並非絕對必要,他們只是爲了便於閱讀。第一個CTE獲取部分匹配列表(1列或更多列),第二個將它們分類,最後一個查詢過濾它們。在第一個CTE中使用'DISTINCT'不會對你有所幫助,但如果你在'Resolved'中取出'DISTINCT',並在'PartialMatches_CTE'中將每個'UNION ALL'改爲'UNION',你都會得到相同的結果。我的直覺是,我寫的版本會更快,但它們都會很慢。 – Aaronaught 2010-01-23 01:52:32

+0

另外,ResolvedMatches_CTE中的第一套'CASE'語句並不是嚴格必要的,要麼是所有你想要的都是不匹配的行。他們只是在那裏幫助快速識別哪些列不匹配,以便他們不必盯着8列或更多列並進行可視化比較。 – Aaronaught 2010-01-23 01:53:29

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而導致的不匹配?

1

正如其他人所說,這個問題需要更多的定義。

比方說你在表1中的對象:

  1. 又大又紅,甜蘋果
  2. 小,綠色,酸蘋果
  3. 中,橙,甜桃
  4. 中,橙色,酸橘

,並在表2中的對象:

  1. 小,紅,甜梅
  2. 大,紅,甜蘋果
  3. 小,綠色,酸蘋果
  4. 小,橙色,甜桔

現在,讓我們通過表1 :

  1. 又大又紅,甜蘋果在表2
  2. 小,綠色,蘋果餡餅比賽第2項沒有匹配 - 哪個列不匹配?
    • 表2,第1項 - 大小,顏色,味道,水果
    • 表2,第1項不匹配 - 不匹配的大小,顏色,味道
    • ...
    • ...
  3. (也有不匹配)
    • ...
    • ...
    • ...
    • ...
  4. (也有不匹配)
    • ...
    • ...
    • ...
    • ...

,你可以看,這很快就成了一個指數問題。每個列表中只有四個項目,您有12個不匹配的對列出列。如果您有10萬件產品和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

+0

我在我的問題中增加了另一個要求。 – 2010-01-23 00:41:59

+0

我猜對了:) – devuxer 2010-01-23 01:01:04

+0

根據情況給出了很好的答案...當然,如果有人決定他們想檢索僅匹配2列的記錄,那麼你就會被洗腦。 ;) – Aaronaught 2010-01-23 01:18:41