假设我有一个DATA表,如:
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
假设我有一个WEIGHTS表(如果你想为了这个讨论而简单,假设所有权重都是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)
例如第一行的 BEST MATCH :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
对于DATA中的每个ID,如何在可能的匹配中找到最佳匹配?
答案 0 :(得分:2)
在此解决方案中,我们进行完全联接以获得所有可能性并评估所有可能性的得分。然后,我们使用ROW_NUMBER为它们分配从最好到最低的数字。最后,我们排除所有那些不是最好的那些“WHERE Rank = 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
答案 1 :(得分: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