2011-01-31 1 views
2

Я пытаюсь сравнить две записи из 6 чисел, каждая из которых может быть равна нулю или 1 (например, 100001 или 011101). Если 3 из 6 соответствуют, я хочу, чтобы выход был .5. Если 2 из 6 матча, я хочу выход быть +0,33 и т.д.Сравнение строк в MySQL с процентом вывода

Вот SQL команды для создания таблицы

CREATE TABLE sim 
(sim_key int, 
string int); 

INSERT INTO sim (sim_key, string) 
VALUES (1, 111000); 

INSERT INTO sim (sim_key, string) 
VALUES (2, 111111); 

Моего желаемого результата, чтобы сравнить две строки, которые разделяют 50% символов и выход 50%.

Возможно ли подобное сравнение в SQL? Заранее спасибо

+0

Не могли бы вы разместить некоторые данные образца в табличном формате и желаемом выходе? – Quassnoi

+0

Не могли бы вы, пожалуйста, подробнее рассказать о проблеме? –

+0

Вывести два числа в одной строке таблицы или они из одного столбца в двух разных строках? Я чувствую, что это возможно, «как» зависит от того, откуда эти цифры. Это потребует вычисления в MySQL, поэтому индексы не будут использоваться - это заставит его медленно запрашивать большой набор данных (возвращая множество строк), но ОК, если вы только сравниваете сразу два числа. – Purpletoucan

ответ

2

Это возвращает процент, равный 1 бит в обеих строках:

select bit_count(conv(a.string, 2, 10) & conv(b.string, 2, 10))/6*100 as percent_match 
from sim a, sim b where 
a.sim_key=1 and b.sim_key=2; 

Как вы храните ваши битовые поля поскольку представление базы 2 преобразуется в числа, нам сначала нужно сделать конверсии: conv(a.string, 2, 10), conv(b.string, 2, 10).

Тогда мы храним только биты, которые равны 1 в каждом поле: conv(a.string, 2, 10) & conv(b.string, 2, 10)

И мы считаем их: bit_count(conv(a.string, 2, 10) & conv(b.string, 2, 10))

И, наконец, мы просто вычислить процент: bit_count(conv(a.string, 2, 10) & conv(b.string, 2, 10))/6 * 100.

Запрос возвращает 50 для 111000 и 111111.

Вот другая версия, которая также рассчитывает совпадающие нули:

select bit_count((conv(a.string, 2, 10) & conv(b.string, 2, 10)) | ((0xFFFFFFFF>>(32-6))&~(conv(a.string, 2, 10)|conv(b.string, 2, 10))))/6*100 as percent_match 
from sim a, sim b where 
a.sim_key=1 and b.sim_key=2; 

Обратите внимание, что, в то время как это решение работает, вы действительно должны сохранить это поле, как это вместо:

INSERT INTO sim (sim_key, string) 
VALUES (1, conv("111000", 2, 10)); 

INSERT INTO sim (sim_key, string) 
VALUES (2, conv("111111", 2, 10)); 

Или для обновления существующих данных:

UPDATE sim SET string=conv(string, 10, 2); 

Тогда этот запрос дает те же результаты (если вы обновляли данные, как описано выше):

select bit_count(a.string & b.string)/6*100 as percent_match 
from sim a, sim b where 
a.sim_key=1 and b.sim_key=2; 

И считать нули тоже:

select bit_count((a.string & b.string) | ((0xFFFFFFFF>>(32-6))&~(a.string|b.string)))/6*100 as percent_match 
from sim a, sim b where 
a.sim_key=1 and b.sim_key=2; 

(заменить 6 сек по размеру ваших битовых полей)

+0

Wow thanks! Это действительно помогает :) – Spencer

+0

После большого анализа я обнаружил, что это не совсем то, что я хочу. Важно также указать, что позиция также имеет значение – Spencer

+0

Это решение должно заботиться о позициях. С какими строками это не работает? Оператор '&' (побитовый и) сохраняет только 1 бит, которые находятся в одном и том же положении в обоих операндах. Тогда функция 'bit_count()' просто подсчитывает их. Таким образом, это считается 1 бит, который находится в обеих строках, в том же положении. – arnaud576875

0

Поскольку вы храните их как числа, вы можете сделать это

SELECT BIT_COUNT(s1.string & s2.string)/BIT_COUNT(s1.string | s1.string) 
FROM sim s1, sim s2 
WHERE s1.sim_key = 1 AND s2.sim_key = 2 
+0

возвращает 0.3333 on (111000, 111111) ;-) – arnaud576875

+0

Вы храните двоичный '11' как одиннадцать? вместо трех –

+0

да, это то, что делает OP в своем вопросе ;-) – arnaud576875