Mysql搜索类似整数通过部分匹配

时间:2012-12-02 11:44:03

标签: mysql matching

确定。我会尝试描述一下我的案例。 我向4位用户提出了6个问题(是/否),并将此答案记录为字符串变量(1-Yes,0-No)。因此,我有:

CREATE TABLE `answers` (
  `user_id` int(10) unsigned NOT NULL,
  `answers` int(6) DEFAULT NULL,
  PRIMARY KEY (`user_id`)
);
INSERT INTO `answers` VALUES ('1', '111111');
INSERT INTO `answers` VALUES ('2', '111000');
INSERT INTO `answers` VALUES ('3', '110011');
INSERT INTO `answers` VALUES ('4', '100001');

现在我正在尝试找到类似于我的'111111'结果的结果(我回答所有问题)。有趣的是50%的匹配行。

用户#1有100%匹配的答案111111 = 111111
用户#2具有50%匹配的答案111000 - > 111111个
......等等

所以我想发现什么查询会为我找到50%匹配的行:)

3 个答案:

答案 0 :(得分:1)

在OP添加架构后,我重写了答案。

首先,这是一个复杂的问题,将它封装在一个存储函数中是有意义的:

DELIMITER ;; -- In case you are using PHPMyAdmin or something like that

-- Calculates the number of matching answers between
-- two users, given the total number of answers each user has made
-- Replace 6 everywhere in this function with the number of questions (if it changes)
CREATE FUNCTION NumberOfMatchingAnswers(p_user1 INT, p_user2 INT) RETURNS INT

BEGIN
DECLARE i INT Default 1; -- Loop counter
DECLARE str_user1 VARCHAR(6); 
DECLARE str_user2 VARCHAR(6); 
DECLARE num_matched_answers INT Default 0;

SET str_user1 = LPAD(p_user1,6,'0');
SET str_user2 = LPAD(p_user2,6,'0');

answer_match_loop : LOOP

    IF SUBSTR(str_user1, i, 1) = SUBSTR(str_user2, i, 1) THEN
        SET num_matched_answers = num_matched_answers + 1;
    END IF;

    SET i = i + 1; -- Basically the equivalent of a FOR loop
    IF i > 6 THEN
        LEAVE answer_match_loop;
    END IF;
END LOOP answer_match_loop;

RETURN num_matched_answers;

END;;

现在我们已经定义了存储的函数,我们可以基于它创建查询:

SELECT user_id FROM Answers WHERE
NumberOfMatchingAnswers(Answers.answers, 101101) >= 3;

此查询将在三个或更多问题中获取与user_id回答相同的所有匹配101101

那么,您如何在系统中使用此查询?

  1. 101101替换为您要与
  2. 进行比较的实际答案集
  3. 如果您发现误报率太高,请将3数字增加,以便您的威胁数超过50%
  4. 编写一个查询,查找匹配率大于50%的所有user_id
  5. 等。等
  6. 注意:如果您希望将系统扩展为不仅采用是/否输入,而且实际允许一系列选项,则此存储的功能将能够应对。因为它比较每个数字,每个问题最多可以有10个可能的答案,它仍然有用。

答案 1 :(得分:1)

BIT_COUNT应该帮助你。

SELECT * FROM table WHERE BIT_COUNT(score)>=3;

此查询假定您有6个问题并查找得分为50%+得分;

如果你插入这样的行

INSERT INTO `answers` VALUES ('1', b'111111');

您不必使用conv。

更准确地说,如果您以这种方式插入分数,它们将被视为二进制,您可以在您的情况下成功使用按位运算符。 所以,如果你这样做。

SELECT user_id, BIT_COUNT(answers) FROM answers

您将获得正确答案的数量。 要从给定分数中得到+/- 2分,那就是

SELECT user_id FROM answers WHERE BIT_COUNT(answers) BETWEEN BIT_COUNT(score_to_compare_with)-2 AND BIT_COUNT(score_to_compare_with)+2 

答案 2 :(得分:0)

我所说的答案可能太复杂了。但是,认为最好分享。

对于所有24个问题,您可能需要生成正确/错误答案的模式作为模式。 将它们存储在一个表中,每个模式都有唯一的ID。

然后将当前答案表列与该模式表进行匹配,以获得总和,计数等。

让我通过一个样本重新解释和解释。此查询将为您提供完全匹配。但是,如果没有完全匹配,您可以进行必要的更改以获得部分匹配。

参考:SQLFIDDLE

你的模式表:

ANSWERS     CONV(BINARY ANSWERS,2,10)
111111      63
111000      56
110011      51
100001      33

你的答案表:

ID  ANSWERS
1   111111
2   111000
3   110011
4   100001
5   111000

查询以显示每场比赛的计数:

select count(*) into @all from scores;
select x.p as b_answer_pattern,
conv(x.p,10,2) as answer_pattern, 
count(x.id)as counts, 
concat(round((count(x.id)/@all)*100,2),'%') as pct
from (
select id, conv(binary answers,2,10) as p
from scores) as x
group by x.p;

结果:

B_ANSWER_PATTERN    ANSWER_PATTERN  COUNTS  PCT
33                  100001           1      20.00%
51                  110011           1      20.00%
56                  111000           2      40.00%
63                  111111           1      20.00%