3

我的数据库中有一个表,表示两件事之间的相似性。就像是:

+------------+------+
| Field      | Type |
+------------+------+
| id_a       | int  |
| id_b       | int  |
| similarity | ???  |
+------------+------+

similarity将保持之间的相似程度id_aid_b百分比,范围可以从 100% 相似(相同的事物)到但不包括0%。我不会为 0% 相似(即完全不同)的事物存储链接。换句话说,我需要存储 range [100, 0)。小数位数不是很重要,但是 1 或 2 会很好。

我通常看到建议的解决方案是使用类似decimal(4,2). 对于我的用例来说,问题在于它存储(100,0].

我提出了两种可能的解决方案,都使用decimal(4,2),但它们看起来都像黑客:

选项1

检索时存储similarity - 0.01并添加0.01背面。就像是:

INSERT INTO similarities (id_a, id_b, similarity) VALUES (1, 2, ? - 0.01);

进而:

SELECT id_a, id_b, similarity + 0.01 FROM similarities;

选项 2

存储 0%-99.99% 的百分比差异,然后在检索时转换为相似度:

SELECT id_a, id_b, 100 - difference AS similarity FROM similarities;

在这两种情况下,我可能会使用创建一个视图MERGE,而不是在查询中留下加法和减法。

还有比这些更好的选择吗?如果没有,你会选择哪个,为什么?

笔记:

我不介意使用其他表示形式,例如[1,0),只要它很好地表示范围即可。

编辑以澄清:

插入很少完成,并且只由我完成,而不是用户完成,并且是大批量完成的。我知道我插入的数据将始终在 [100,0) 中,因此这不是强制执行的问题,而是最有效/最自然的表示形式是什么

4

2 回答 2

2

在符合 SQL 标准的 dbms 中,您可以将列声明为 decimal(5, 2) 类型(或使用等效的小数部分),并使用 CHECK 约束来限制范围。

create table data (
  id integer primary key,
  pct decimal(5, 2) not null check (pct > 0 and pct <= 100)
);

但是 MySQL 不符合 SQL 标准。它不强制执行 CHECK 约束。所以我认为你有两个选择。

  1. 编写一个触发器来检查范围,并回滚超出您选择的范围的插入和更新。
  2. 使用对有效值表的外键引用。在您的情况下,该表将只有 10,000 行,对吗?

如果我需要在进一步计算中使用百分比,我更喜欢 0.0001 到 1.0000 范围内的值,因此可以直接使用它们。不过,看起来这不是您的应用程序中的一个问题。

于 2013-02-08T14:03:28.040 回答
0

与其将相似度分配为百分比,不如按 sè 为它们提供范围内的相似度分数[1,10000](或者(0,10000]如果您愿意)。每个百分点给你 100 分(如果你需要,可以有效地保留两位小数)。

贮存:int(32)

看法:SELECT id_a, id_b, similarity/100 FROM similarities;

于 2013-02-08T14:24:35.013 回答