如何比较每一行并获得最佳结果?

时间:2014-01-15 23:42:03

标签: sql sql-server-2008

假设我有一个值和类别表:

+--+-----+---+
|ID|value|cat|
+--+-----+---+
|0 |1    |0  |
+--+-----+---+
|1 |3    |0  |
+--+-----+---+
|2 |2    |1  |
+--+-----+---+
|3 |1.2  |1  |
+--+-----+---+
|4 |1    |1  |
+--+-----+---+

我想知道,对于每一行,与最接近的值匹配的行的ID属于同一类别,我也想知道差异。

因此对于行ID=0,正确答案为ID=1,差值为2。正确的输出是:

+--+----------+----------+
|ID|difference|best match|
+--+----------+----------+
|0 |2         |1         |
+--+----------+----------+
|1 |2         |0         |
+--+----------+----------+
|2 |0.8       |3         |
+--+----------+----------+
|3 |0.2       |4         |
+--+----------+----------+
|4 |0.2       |3         |
+--+----------+----------+

我只是在学习CROSS JOIN,虽然我确信这可以做到但我真的不知道从哪里开始。

1 个答案:

答案 0 :(得分:2)

您可以通过自我加入并将ROW_NUMBER()功能与MIN()结合使用来实现此目的:

;WITH cte AS (SELECT a.ID aID
                    ,MIN(ABS(a.value - b.value)) diff
                    ,ROW_NUMBER() OVER(PARTITION BY a.ID ORDER BY MIN(ABS(a.value - b.value)))RN
                    ,b.ID bID
              FROM Table1 a
              JOIN Table1 b
                ON a.cat = b.cat
                AND a.ID <> b.ID
              GROUP BY a.ID,b.ID)
SELECT  aID
       ,diff
       ,bID Best_Match
FROM cte
WHERE RN = 1

演示:SQL Fiddle

如果您希望在出现平局时返回多行,则需要使用RANK()代替ROW_NUMBER()