2013-12-16 178 views
3

我有一個字符串「標識符」的表,我想匹配一個「組」表,找到「最佳匹配」(即:包含較長部分的匹配的字符串)。例如:假設我有兩個組:「19」和「19.10」。我要的是:SQL:加入最佳字符串匹配

  • item "19.10.1" is part of the group "19.10"
  • item "19.10.xxxx" is part of the group "19.10"
  • item "19.20" is part of the group "19"

我得到了什麼到現在是這樣的:

SELECT * FROM Items i 
LEFT JOIN MyGroup g ON g.Prefix = SUBSTRING(i.ItemID,1,LEN(g.Prefix)) 

,所有的字符串相匹配,但我不知道如何過濾「最佳匹配」(即較長的匹配)fr om我的結果。

順便說一句,我的工作SQL Server 2005的

例如,SQL小提琴上: http://sqlfiddle.com/#!3/9a9d8/1

+0

1)你能改變你的gro的結構嗎?起牀桌?能夠提前分解GroupDesc或添加「分數」列可能會有幫助。 2)您可能需要查看[PARSENAME](http://technet.microsoft.com/en-us/library/ms188006.aspx)函數,這可能有助於抓取對象ID的位,具體取決於它們確切的規格。 –

+0

是的,我可以添加「評分」欄......但我無法理解這對我的情況有何幫助。謝謝你的回覆 – Nova

回答

4

試試這一個。

SELECT t.ItemID, g1.prefix, g1.GroupDesc 
FROM Items i1 
LEFT JOIN MyGroup g1 ON g1.Prefix = SUBSTRING(i1.ItemID,1,LEN(g1.Prefix)) 

RIGHT JOIN 

(

    SELECT i2.ItemID, max(len(g2.prefix)) AS ln 
    FROM Items i2 
    LEFT JOIN MyGroup g2 ON g2.Prefix = SUBSTRING(i2.ItemID,1,LEN(g2.Prefix)) 
    GROUP BY i2.ItemID 

) t ON i1.ItemID = t.ItemID AND len(g1.prefix) = t.ln 

您可以測試它在這個測試數據:

CREATE TABLE dbo.MyGroup 
     (GroupDesc VARCHAR(100), 
     Prefix VARCHAR(10)); 
    CREATE TABLE dbo.Items 
     (ItemDesc VARCHAR(100), 
     ItemID VARCHAR(10)); 

    INSERT INTO MyGroup (GroupDesc, Prefix) 
    VALUES ('Group A', '19'); 
    INSERT INTO MyGroup (GroupDesc, Prefix) 
    VALUES ('Group B', '19.10'); 
    INSERT INTO MyGroup (GroupDesc, Prefix) 
    VALUES ('Group C', '19.10.3'); 

    INSERT INTO Items (ItemDesc, ItemID) 
    VALUES ('Item 1', '19.10.4'); 
    INSERT INTO Items (ItemDesc, ItemID) 
    VALUES ('Item 2', '19.10.3'); 
    INSERT INTO Items (ItemDesc, ItemID) 
    VALUES ('Item 3', '19.20'); 
    INSERT INTO Items (ItemDesc, ItemID) 
    VALUES ('Item 4', '44.55'); 
+0

彼得:謝謝。這工作正常。我只是想知道查詢是否可以「優化」存儲組表中的前綴的長度(如上面評論中所建議的) – Nova

+1

@Nova是的,如果您在組表中存儲前綴的長度,查詢將變得更簡單,因爲你將擺脫LEN(g1.Prefix)和LEN(g2.Prefix),並將它們替換爲g1.len和g2.len之類的東西。 –

+0

@Nova是的,這就是我的建議 - 有效的是,如果您在組表中存儲每個前綴長度的「分數」,生活變得更容易,因爲您可以看到哪個匹配具有最高的分數來選擇正確的一個。 –

1

我想出了這一點:

with tmp as 
(
    SELECT * FROM Items i 
    LEFT JOIN MyGroup g ON g.Prefix = SUBSTRING(i.ItemID,1,LEN(g.Prefix)) 
) 
SELECT a.* FROM tmp a WHERE LEN(a.prefix) = (SELECT MAX(LEN(b.prefix)) FROM tmp b WHERE a.itemid = b.itemid) 

似乎工作...

SQLFiddle

+0

在上面嘗試查詢我的測試數據。似乎沒有工作。 –

+0

@ peter.petrov也許我不太明白你想要什麼。我做了一些改變,現在可以嗎? – xpy

+0

不,我不是OP。現在,您的查詢更好,但它不會爲我的測試數據返回任何'項目4'。但現在好多了,是的。 –