私は2つのテーブルを持っています:
Quest
- (int) id
- (text) characters
User
- (int) id
- (text) characters
エントリは次のようになります。
クエスト
id | characters
1 | abcdefgh
2 | mkorti
3 | afoxi
4 | bac
ユーザー
id | characters
1 | abcd
ここで、ユーザーにとって最も簡単なクエストを選択したいと思います。最も簡単なクエストは、quest.characters と user.characters の交差が最も多いものです。したがって、この例では、リストは次のようになります (user.id = 1 の場合):
questid | easiness
4 | 100
1 | 50
3 | 40
2 | 0
簡単さは、何パーセント一致したかを示すだけです。MySQL でこのような列の交差を作成することは可能ですか? パフォーマンスはどうですか?実際、私も関係を持っています (クエスト -> キャラクターとユーザー -> キャラクター) が、あまりパフォーマンスが良くないと思います。数千のクエストと数千のキャラクターがあるからです。
更新 #1
わかりました、リレーショナルはまだ進むべき道のようです。今、私のテーブルは次のようになります。
CREATE TABLE IF NOT EXISTS `quest` (
`questid` int(10) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`questid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
CREATE TABLE IF NOT EXISTS `questcharacters` (
`questid` int(10) unsigned NOT NULL,
`characterid` int(10) unsigned NOT NULL,
PRIMARY KEY (`questid`,`characterid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `single_character` (
`characterid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`single_char` varchar(10) NOT NULL,
PRIMARY KEY (`characterid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `user` (
`userid` int(10) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `usercharacters` (
`userid` int(10) unsigned NOT NULL,
`characterid` int(10) unsigned NOT NULL,
PRIMARY KEY (`userid`,`characterid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
PS .: なぜsingle_char
データ型として VARCHAR(10) があるのか不思議ではありませんが、私はマルチバイト値を使用し、MySQL がそれらを char(1) に対してどのように処理するかわかりません。だから私はそこで寛大でした。
アップデート #2
今のところ私のクエリは次のとおりです。
SELECT usercharacters.userid, questcharacters.questid
FROM `usercharacters`
LEFT OUTER JOIN questcharacters ON usercharacters.characterid = usercharacters.characterid
GROUP BY questcharacters.questid, usercharacters.userid;
しかし、簡単さ/重複する文字を計算する方法は? どのフィールドに COUNT() を適用する必要がありますか?
アップデート #3
さて、このクエリで動作しているようです(サブセレクトを使用):
SELECT usercharacters.userid as uid, questcharacters.questid as qid, (SELECT COUNT(questcharacters.characterid) FROM questcharacters LEFT OUTER JOIN usercharacters ON questcharacters.characterid = usercharacters.characterid WHERE questcharacters.questid = qid) as questcount
FROM `usercharacters`
LEFT OUTER JOIN questcharacters ON usercharacters.characterid = usercharacters.characterid
GROUP BY questcharacters.questid, usercharacters.userid;
アップデート #4
SELECT usercharacters.userid as uid, questcharacters.questid as qid, (SELECT COUNT(questcharacters.characterid) FROM questcharacters LEFT OUTER JOIN usercharacters ON questcharacters.characterid = usercharacters.characterid WHERE questcharacters.questid = qid) as user_knows, (SELECT COUNT(questcharacters.characterid) FROM questcharacters WHERE questcharacters.questid = qid) as total_characters
FROM `usercharacters`
LEFT OUTER JOIN questcharacters ON usercharacters.characterid = usercharacters.characterid
GROUP BY questcharacters.questid, usercharacters.userid
ORDER BY total_characters / user_knows DESC;
今欠けているのは、簡単さを選択することだけです。(ORDER BY 句と同様)。誰でもこれを行う方法を知っていますか?