我如何计算在一个MySQL查询两个散列之间的区别?

问题描述 投票:4回答:3

我试图计算输入的散列和数据库存储的哈希值之间的汉明距离。这些都是感性的哈希值,所以它们之间的汉明距离对我很重要,告诉我多么相似的两个不同的图像(见http://en.wikipedia.org/wiki/Perceptual_hashinghttp://jenssegers.com/61/perceptual-image-hasheshttp://stackoverflow.com/questions/21037578/)。哈希值是16个十六进制字符长,看起来像这样:

乙1 d 0 X 44个A 4个Aboukboukhas 1 Aftsfoukheedad 4扇区1 阿751 0 19 0 P Sehoudaf

我的数据库看起来是这样的:

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

mysql hash bit-manipulation hamming-distance phash
3个回答
4
投票

这个问题似乎与您所选择的数据类型是一个字符串类型。使用数字数据类型,在MySQL 5.7和8.0的工作原理:

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

Demo on 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,返回一个变量,而5.7的MySQL被返回值是异或,这表明它是在数值上下文处理BINARY字符串作为0。


2
投票

这是不是一个数字,所以它不能用于数学计算:

`hash` binary(8) NOT NULL

使用BIGINT代替:

`hash` bigint unsigned NOT NULL

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;
© www.soinside.com 2019 - 2024. All rights reserved.