5

我正在尝试计算输入哈希和数据库存储的哈希之间的汉明距离。这些是感知散列,所以它们之间的汉明距离对我来说很重要,并告诉我两个不同的图像有多相似(参见http://en.wikipedia.org/wiki/Perceptual_hashinghttp://jenssegers.com/61/感知图像哈希http ://stackoverflow.com/questions/21037578/ )。哈希是 16 个十六进制字符长,如下所示:

b1d0c44a4eb5b5a9
1f69f25228ed4a31
751a0b19f0c2783f

我的数据库如下所示:

CREATE TABLE `hashes` (
  `id` int(11) NOT NULL,
  `hash` binary(8) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;

INSERT INTO `hashes` (`id`, `hash`) VALUES
    (1, 0xb1d0c44a4eb5b5a9),
    (2, 0x1f69f25228ed4a31),
    (3, 0x751a0b19f0c2783f);

现在,我知道我可以像这样查询汉明距离:

SELECT BIT_COUNT(0xb1d0c44a4eb5b5a9 ^ 0x751a0b19f0c2783f)

正如预期的那样,它将输出 38。但是,我似乎无法为此比较引用列名。以下不按预期工作。

SELECT BIT_COUNT(hash ^ 0x751a0b19f0c2783f) FROM hashes

有谁知道我如何SELECT使用我的数据库中的列来计算像上面的第一个查询一样的汉明距离?我已经尝试了无数使用hex(), unhex(), conv(), 和cast()不同方式的场景。这是在 MySQL 中。

更新我上面的查询在 MySQL v8 中运行时似乎按预期工作(感谢@LukStorms 指出这一点)。您可以使用下面的小提琴并更改左上角的版本。我现在的问题是:如何确保该行为适用于所有版本的 MySQL?

小提琴:https ://www.db-fiddle.com/f/mpqsUpZ1sv2kmvRwJrK5xL/0

4

3 回答 3

4

该问题似乎与您选择的字符串类型的数据类型有关。在 MySQL 5.7 和 8.0 中使用 numeric 数据类型:

CREATE TABLE `hashes` (
  `id` int(11) NOT NULL,
  `hash` bigint unsigned NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;

INSERT INTO `hashes` (`id`, `hash`) VALUES
    (1, 0xb1d0c44a4eb5b5a9),
    (2, 0x1f69f25228ed4a31),
    (3, 0x751a0b19f0c2783f);

SELECT id, HEX(hash), BIT_COUNT(hash ^ 0x751a0b19f0c2783f)
FROM hashes;

输出:

id  HEX(hash)           BIT_COUNT(hash ^ 0x751a0b19f0c2783f)
1   B1D0C44A4EB5B5A9    38
2   1F69F25228ED4A31    34
3   751A0B19F0C2783F    0

dbfiddle 上的演示

通过这个查询可以看出 MySQL 5.7 和 8.0 使用字符串类型的区别:

SELECT id, hash, HEX(hash), HEX(hash ^ 0x751a0b19f0c2783f)
FROM hashes;

MySQL 5.7:

id  hash                                                        HEX(hash)           HEX(hash ^ 0x751a0b19f0c2783f)
1   {"type":"Buffer","data":[177,208,196,74,78,181,181,169]}    B1D0C44A4EB5B5A9    751A0B19F0C2783F
2   {"type":"Buffer","data":[31,105,242,82,40,237,74,49]}       1F69F25228ED4A31    751A0B19F0C2783F
3   {"type":"Buffer","data":[117,26,11,25,240,194,120,63]}      751A0B19F0C2783F    751A0B19F0C2783F

MySQL 8.0

id  hash                                                        HEX(hash)           HEX(hash ^ 0x751a0b19f0c2783f)
1   {"type":"Buffer","data":[177,208,196,74,78,181,181,169]}    B1D0C44A4EB5B5A9    C4CACF53BE77CD96
2   {"type":"Buffer","data":[31,105,242,82,40,237,74,49]}       1F69F25228ED4A31    6A73F94BD82F320E
3   {"type":"Buffer","data":[117,26,11,25,240,194,120,63]}      751A0B19F0C2783F    0000000000000000

MySQL 8.0 正确执行 XOR,返回一个变量,而 MySQL 5.7 返回被 XOR'ed 的值,表明它BINARY在数字上下文中将字符串视为 0。

于 2019-02-02T22:52:02.020 回答
2

这不是一个数字,因此不能用于数学计算:

`hash` binary(8) NOT NULL

改用 bigint:

`hash` bigint unsigned NOT NULL
于 2019-02-02T22:51:14.520 回答
2

尝试这个:

SELECT id, HEX(hash), CAST(CONV(HEX(hash),16,10) AS UNSIGNED), BIT_COUNT(CAST(CONV(HEX(hash),16,10) AS UNSIGNED) ^ 0x751a0b19f0c2783f) FROM hashes;
于 2019-02-03T00:21:42.643 回答