3

好的。我将尝试详细描述我的案例。我已经向 4 个用户提出了 6 个问题(是/否),并将这个答案记录为字符串变量(1-是,0-否)。因此,我有:

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% 的匹配行:)

4

3 回答 3

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中回答相同的所有匹配s。101101

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

  1. 替换101101为您要比较的实际答案集
  2. 如果您发现误报太多,请增加数量3,使您的阈值高于 50%
  3. 编写一个查询,找出所有user_id匹配度大于 50% 的 s 对
  4. 等等等等。

注意:如果您希望将系统扩展为不仅接受是/否输入,而且实际上允许一系列选项,那么这个存储的函数将能够应付。因为它比较每个数字,所以每个问题最多可以有 10 个可能的答案,它仍然可以工作。

于 2012-12-02T11:49:33.693 回答
1

BIT_COUNT应该可以帮助您。

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

此查询假设您有 6 个问题并查找分数为 50%+ 的分数;

如果您插入这样的行

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

您不必使用转换。

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

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 
于 2012-12-02T12:15:00.430 回答
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%
于 2012-12-02T18:24:49.040 回答