2015-04-02 30 views
4

假設我有這樣一個數據表:使用記分找到最佳匹配在SQL

ID | Col1 | Col2 | Col3 
1 a  b  23 
2 a  c  14 
3 f  g  11 

假設我有一個POSSIBLE_MATCHES表所示:

MatchID | Col1 | Col2 | Col3 
101   a  a  11 
102   a  b  11 
103   a  b  14 
104   a  c  23 
105   f  a  1 

假設我有一個權係數表像(如果你想爲了這個討論和簡單的假設所有的權重是1 - 我可以在稍後提出我的解決方案以合併重量):

Col | Weight 
Col1 1 
Col2 1.5 
Col3 2 

因此,對於每個可能的匹配,我們將計算每個匹配列上的SCORE

Score = Col1 Weight * (CASE WHEN DATA.COL1 = POSSIBLE_MATCHES.Col1 THEN 1 ELSE 0) + 
      Col2 Weight * (CASE WHEN DATA.COL2 = POSSIBLE_MATCHES.Col2 THEN 1 ELSE 0) + 
      Col3 Weight * (CASE WHEN DATA.COL3 = POSSIBLE_MATCHES.Col3 THEN 1 ELSE 0) 

因此,例如最佳匹配用於第一行:Col1中= A,Col2中= B,COL3 = 23:

MatchID | Col1 | Col2 | Col3 | Score 
101   a  a  11  1*1 + 1.5*0 + 2*0 = 1 
102   a  b  11  1*1 + 1.5*1 + 2*0 = 2.5 
103   a  b  14  1*1 + 1.5*1 + 2*0 = 2.5 
104   a  c  23  1*1 + 1.5*0 + 2*1 = 3 
105   f  a  1  1*0 + 1.5*0 + 2*0 = 0 

因此,在這種情況下爲ID的最佳匹配: 1是MatchID:104。如果分數相同,則採用最低的MatchID。

這裏有一個SQL小提琴,如果你想玩弄這樣的: http://sqlfiddle.com/#!6/9df45/1

對於數據的每個ID我怎麼會發現在可能的匹配最佳匹配?

+0

最佳匹配是MatchID得分最高 – Denis 2015-04-02 14:15:48

+0

因此,解決方案是正確加入表格,評估分數並選擇最高分數的匹配。你究竟在哪裏卡住? – 2015-04-02 14:18:07

+0

@ThorstenKettner:是的。只需要指導一下如何做這樣的事情。 – Denis 2015-04-02 14:22:47

回答

1

試試這個:

DECLARE @d TABLE(ID INT, Col1 CHAR(1), Col2 CHAR(1), Col3 INT) 
DECLARE @m TABLE(ID INT, Col1 CHAR(1), Col2 CHAR(1), Col3 INT) 


INSERT INTO @d VALUES 
(1, 'a', 'b', 23), 
(2, 'a', 'c', 14), 
(3, 'f', 'g', 11) 

INSERT INTO @m VALUES 
(101, 'a', 'a', 11), 
(102, 'a', 'b', 11), 
(103, 'a', 'b', 14), 
(104, 'a', 'c', 23), 
(105, 'f', 'a', 1) 


SELECT DataID, MatchID FROM 
(
    SELECT d.ID AS DataID, 
      m.ID AS MatchID, 
       ROW_NUMBER() OVER(PARTITION BY d.ID ORDER BY 
       CASE WHEN d.Col1 = m.Col1 THEN 1 ELSE 0 END * 1 + 
       CASE WHEN d.Col2 = m.Col2 THEN 1 ELSE 0 END * 1.5 + 
       CASE WHEN d.Col3 = m.Col3 THEN 1 ELSE 0 END * 2 DESC) AS rn 

    FROM @d d 
    CROSS JOIN @m m 
) t WHERE rn = 1 

輸出:

DataID MatchID 
1  104 
2  103 
3  102 
+0

沒想到這會是這麼簡單... – Denis 2015-04-02 14:36:44

2

在此解決方案中,我們完全加入以獲得所有可能性並評估所有人的分數。然後,我們用ROW_NUMBER從最高到最低分配一個數字。最後,我們排除所有那些不是最好的一個與 「WHERE排名= 1」

SELECT * 
FROM 
(SELECT data.ID, 
     possible_matches.MatchID, 
     Score = (CASE WHEN data.Col1 = possible_matches.Col1 THEN 1 ELSE 0 END) * 1 + 
       (CASE WHEN data.Col2 = possible_matches.Col2 THEN 1 ELSE 0 END) * 1.5 + 
       (CASE WHEN data.Col3 = possible_matches.Col3 THEN 1 ELSE 0 END) * 2, 
     [Rank] = ROW_NUMBER() OVER(PARTITION BY data.ID ORDER BY (CASE WHEN data.Col1 = possible_matches.Col1 THEN 1 ELSE 0 END) * 1 + 
                  (CASE WHEN data.Col2 = possible_matches.Col2 THEN 1 ELSE 0 END) * 1.5 + 
                  (CASE WHEN data.Col3 = possible_matches.Col3 THEN 1 ELSE 0 END) * 2 DESC) 
from data, possible_matches) AS AllScore 
WHERE AllScore.[Rank] = 1 
+0

只是注意到我忘了把DESC排序。我加了它 – AXMIM 2015-04-02 14:37:32