回答を文字列に連結します。yes/no の場合は 2 進数に少し似ていますが、16 を超えるオプションと 100 未満のオプションがある場合、または仕切りなどを使用する場合は、他の数字、16 進数、またはペアを使用しても害はありません。
最も近い一致を見つけるには、各位置の各文字を比較し、結果をランク付けします。
ランク = 指定された比較文字列で同じである文字の量 (例: "0101101001")
0101101001 against 0101101001 gives a rank of 10
0101101001 against 1101101001 gives a rank of 9
0101101001 against 1111111001 gives a rank of 7
0101101001 against 0001100111 gives a rank of 6
SQLとして
table `yesno`
| user_id | answers |
| 1 | 0101101001 |
| 2 | 1101101001 |
etc
SELECT answers,
( #looking for 0101101001
IF (substring(answers,1,1)=0, 1, 0)
+ IF (substring(answers,2,1)=1, 1, 0)
+ IF (substring(answers,3,1)=0, 1, 0)
+ IF (substring(answers,4,1)=1, 1, 0)
+ IF (substring(answers,5,1)=1, 1, 0)
+ IF (substring(answers,6,1)=0, 1, 0)
+ IF (substring(answers,7,1)=1, 1, 0)
+ IF (substring(answers,8,1)=0, 1, 0)
+ IF (substring(answers,9,1)=0, 1, 0)
+ IF (substring(answers,10,1)=1, 1, 0)
)
AS rank
FROM yesno
ORDER BY
( #looking for 0101101001
IF (substring(answers,1,1)=0, 1, 0)
+ IF (substring(answers,2,1)=1, 1, 0)
+ IF (substring(answers,3,1)=0, 1, 0)
+ IF (substring(answers,4,1)=1, 1, 0)
+ IF (substring(answers,5,1)=1, 1, 0)
+ IF (substring(answers,6,1)=0, 1, 0)
+ IF (substring(answers,7,1)=1, 1, 0)
+ IF (substring(answers,8,1)=0, 1, 0)
+ IF (substring(answers,9,1)=0, 1, 0)
+ IF (substring(answers,10,1)=1, 1, 0)
)
DESC
PHPとして
#usage $rs=getUsersByRank("0101101001");
function getUsersByRank($lookslike) {
/* expects "binary" string
returns user_id, answers and rank (0 to string length) ordered by closest match first
*/
$ifs=array();
foreach (str_split($lookslike) as $i=>$bit){
$ifs[]='IF (substring(answers,' . ($i+1) . ',1)=' . $bit . ', 1, 0) ';
}
// use your db class
return $db->select_many('
SELECT user_id, answers,
( '. implode(' + ', $ifs) .' )
AS rank
FROM yesno
ORDER BY
( '. implode(' + ', $ifs) .' )
DESC
');
}
各ユーザーを他の各ユーザーと比較したい場合は、user1、user2、match_rank を格納する別のテーブルが必要になります。
getUsersByRank() で結果を制限したい場合があります。
これが機能することを実際にテストしたわけではなく、書き留めただけです。