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。最简单的任务是 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 子句中)。任何人都知道如何做到这一点?

4

2 回答 2

0

如果您实际上有questcharacter桌子usercharacters,那么这是最好的方法:

SELECT uc.id AS userid, 
       qc.id AS qcid, 
       COUNT(*) AS NumCharacters,
       COUNT(qc.char) AS Nummatches,
       COUNT(qc.char) / count(*) AS Easiness
FROM UserCharacters uc 
   LEFT OUTER JOIN QuestCharacters qc ON uc.char = qc.char
WHERE uc.id = 1
   GROUP BY uc.id, qc.id
   ORDER BY easiness DESC
LIMIT 1

如果您只将它们作为字符串 - SQL 并不漂亮。您必须进行交叉连接和大量字符串操作。最好的方法是以关系数据库的形式(每个列表元素一行)使事物更加规范化,而不是将列表嵌入字符串中。

于 2013-07-15T17:35:18.660 回答
0

所以这是我的最终和可行的解决方案:

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, 
       (SELECT ( Count(questcharacters.characterid) / (SELECT 
                         Count(questcharacters.characterid) 
                                                       FROM   questcharacters 
                                                       WHERE 
                 questcharacters.questid = qid) ) 
        FROM   questcharacters 
               LEFT OUTER JOIN usercharacters 
                            ON questcharacters.characterid = 
                               usercharacters.characterid 
        WHERE  questcharacters.questid = qid) AS ratio 
FROM   `usercharacters` 
       LEFT OUTER JOIN questcharacters 
                    ON usercharacters.characterid = usercharacters.characterid 
GROUP  BY questcharacters.questid, 
          usercharacters.userid 
ORDER  BY ratio DESC; 

我真的需要那么多子选择吗?

于 2013-07-15T19:01:53.040 回答