Oracle select 相似值

Oracle select similar values

我有一个数据库 table 有很多这样的值:340.13 和 232.89。

现在我想select与比较值最匹配的值。

不费吹灰之力就可以做到吗?

这将匹配搜索值 +-10% 范围内的值,如果有多个值,将根据绝对差异找到最接近的匹配项。

SQL Fiddle

Oracle 11g R2 模式设置:

CREATE TABLE TABLE_NAME ( VALUE ) AS
SELECT 340.13 FROM DUAL UNION ALL
SELECT 232.89 FROM DUAL UNION ALL
SELECT 224.73 FROM DUAL UNION ALL
SELECT 100.00 FROM DUAL;

查询 1:

WITH search_values ( search_value ) AS (
  SELECT 330 FROM DUAL UNION ALL
  SELECT 230 FROM DUAL
)
SELECT search_value,
       value
FROM   (
  SELECT search_value,
         value,
         RANK() OVER ( PARTITION BY Search_value 
                       ORDER BY ABS( value - search_value ) ) AS rnk
  FROM   table_name t
         INNER JOIN
         search_values v
         ON ( t.value BETWEEN search_value * 0.9 AND search_value * 1.1 )
)
WHERE  Rnk = 1

Results:

| SEARCH_VALUE |  VALUE |
|--------------|--------|
|          230 | 232.89 |
|          330 | 340.13 |

这是一个非常基本和常见的任务,所以这里是一般方法。

首先你需要决定"best-match-criteria"。基本上它作为存储在行和输入值中的值的函数。所以你可以实现这个函数并评估它,为每一行调用类似 MATCH_RATING(COLUMN, :value) 的东西。现在你对每一行都有这个 rating,你可以按照你喜欢的任何方式对行进行排序并过滤最合适的行(ROWNUM 非常适合这个,分析函数也是如此RANKROW_NUMBER).

SELECT *
FROM (
  SELECT VALUE,
         MATCH_RATING(VALUE, :input_value)   RATING
  FROM   YOUR_TABLE
  ORDER BY RATING DESC)
WHERE ROWNUM = 1

那么一个好主意是检查您选择的标准是否以语言实现,因为如果是,使用 SQL 功能肯定会在性能方面更好。

例如,如果两个数字之间的距离是您唯一关心的事情,SQL 将看起来像这样。

SELECT VALUE
FROM (
  SELECT VALUE,
         ABS(VALUE - :input_value)  DISTANCE
  FROM   YOUR_TABLE
  ORDER BY DISTANCE)
WHERE ROWNUM = 1

如果您的 函数 在某个时间间隔内假定值为 0,这意味着某些行永远不会进入您的结果集,那么您还应该使用 WHERE 子句过滤无用的行(WHERE MATCH_RATING(COLUMN, :value) > 0).

回到我们的距离示例:让我们接受距离不超过输入值的 5%。

SELECT VALUE
FROM (
  SELECT VALUE,
         ABS(VALUE - :input_value)  DISTANCE
  FROM   YOUR_TABLE
  WHERE  VALUE BETWEEN 0.95 * :input_value AND 1.05 * :input_value
  ORDER BY DISTANCE)
WHERE ROWNUM = 1

顺便说一句,YOUR_TABLE.VALUE 上的索引肯定会对这个例子有所帮助。