2016-04-29 2 views
0

У меня есть ряд blockhash на основе отпечатков пальцев изображений, хранящихся в таблице вместе с членом веб-сайт, который загрузил его и локальный URL изображения:Как я могу структурировать запрос MySQL, который ссылается на выбор результатов в вычислениях?

member varchar(8) 
fingerprint char(64) 
url  varchar(80) 

Я пытаюсь сделать расчет расстояния Хемминга на эти хэши, чтобы определить, насколько вероятно, что они будут соответствовать (ссылка mysql hamming distance between two phash).

Учитывая самый простой способ, который я видел, это использовать функцию bit_count MySql для XOR двух и произвести общее количество бит, я знаю, что мне нужно разбить хэш 64 символов на 4 куска, затем конвертируйте их в целое число без знака перед его подачей на бит_count. Таким образом, у меня есть запрос, который делает такой (запуск из командной строки Linux, следовательно, аргумент переменные):

select bit_count(cast(conv(substr('$1', 1, 16), 16, 10) as unsigned)^cast(conv(substr($2, 1, 16), 16, 10) as unsigned)) + 
bit_count(cast(conv(substr('$1', 17, 16), 16, 10) as unsigned)^cast(conv(substr('$2', 17, 16), 16, 10) as unsigned)) + 
bit_count(cast(conv(substr('$1', 33, 16), 16, 10) as unsigned)^cast(conv(substr('$2', 33, 16), 16, 10) as unsigned)) + 
bit_count(cast(conv(substr('$1', 49, 16), 16, 10) as unsigned)^cast(conv(substr('$2', 49, 16), 16, 10) as unsigned)); 

..И это производит соответствующие результаты между двумя отпечатками пальцев.

Однако мне нужен запрос, который найдет подходящие отпечатки пальцев от кого-либо другого, кроме рассматриваемого участника. В основном:

select member, url 
from images 
where (Hamming Distance between <fingerprint> and (select hashes from member) < 10) 
    AND member != "<value>" 

Я думаю, что я мог бы создать хранимую процедуру для определения расстояния Хемминга, то, возможно, ограничить результаты, которые я должен проверить из всей базы данных на что-то вроде тех, которые удовлетворяют первые 10 символов. Но есть ли лучший способ?

+0

Используйте соединение между 'изображениями' и' member'. – Barmar

ответ

1

A hamming_distance сохраненная функция - хорошая идея. Затем вы можете использовать его в соединении.

SELECT i1.member, i1.url 
FROM images AS i1 
JOIN images AS i2 ON i1.member != i2.member AND hamming_distance(i1.fingerprint, i2.fingerprint) < 10 
WHERE i2.member = @member_in_question 
1

Функция была трюком. Он фрагментирует отпечаток пальца и возвращает расстояние между ними. Тогда это был простой вопрос отборным:

select member, url, fingerprint, hamming_dist(fingerprint, '$fingerprint') as distance from images where hash REGEXP '$find' && hamming_dist(hash, '$hash') < 8 && member != '$member';" 

REGEXP ограничивается поиском до возможных совпадений, он состоял из первого и последнего символа в отпечатках пальцев. Это уменьшило время запроса с 0,35 секунды до 0,12 секунды.

Спасибо за помощь!