我正在使用 Wordpress 测验插件。它有两个表(实际上更多,但我试图专注于这个问题)——“questions”和“questionpots”:
‘questions’: QuestionID ---- Question ---- potID
‘questionpots’: potID ---- potName
默认查询是: $SQL = '从问题中选择 * WHERE potID='.$potID;
因此,默认情况下,每个问题都分配给一个特定的池(“问题”表中的“potID”),并且关系是“一对多”。我想做的是将问题分配给多个 jar ,例如“罗马何时沦陷?”的问题。会被问到是否有人选择“罗马历史”锅或“古代历史”锅。
所以我添加了第三个表“relations”,它匹配 QuestionID 和 potID。 问题是我无法弄清楚从“questions”WHERE potID='.$potID 中选择 * 的查询,假设 $potID 有一个或多个问题。
我应该如何加入这个表? 谢谢。
最佳答案
为了解决两个实体之间的多对多关系,我们添加第三个表,即关系表,其中外键引用两个实体表。
添加到关系表中的一行代表两个实体之间的(等等...)关系。
举个例子,假设表 question
和 pot
都有一个 id
列作为主键:
CREATE TABLE question_pot
( question_id INT UNSIGNED NOT NULL COMMENT 'fk ref question'
, pot_id INT UNSIGNED NOT NULL COMMENT 'fk ref pot'
, PRIMARY KEY (question_id, pot_id)
, CONSTRAINT FK_question_pot_question
FOREIGN KEY (question_id) REFERENCES question(id)
, CONSTRAINT FK_question_pot_pot
FOREIGN KEY (pot_id) REFERENCES pot(id)
) ENGINE=InnoDB
要将question id=444
与两个pot pot id=7
和pot id=13
之间的关系添加:
INSERT INTO question_pot VALUES (444,7), (444,13);
并废弃 question
表中的 pot_id
列。您可以先保存这些...
INSERT INTO question_pot (question_id, pot_id)
SELECT q.id
, q.pot_id
FROM question q
WHERE q.pot_id IS NOT NULL
;
然后从问题
中删除pot_id列。
如果您已经做到了这一点,现在您只需要执行 JOIN 操作...
要获取pot id=13
中的所有问题,例如:
SELECT q.*
FROM question q
JOIN question_pot r
ON r.question_id = q.id
WHERE r.pot_id = 13
跟进
上面的查询给出了为表分配别名,并使用别名限定列引用的示例。
限定列引用文献是最佳实践;它使人们更容易阅读和解释该语句,而不需要他们查找表的定义来找出哪列来自哪个表。
将上面的查询与此进行比较:
SELECT *
FROM question
JOIN question_pot
ON question_id = id
WHERE pot_id = 13
现在,尝试回答以下问题:id
是否是对 question
或 question_pot
中的列的引用。 (如果此查询位于 MySQL 存储程序(过程、函数、触发器)中,则对 id
的引用是对列的引用,还是对过程变量的引用。)
在某些情况下,当引用可以引用多个表中的列时,我们必须限定列引用以使引用明确,并导致 MySQL 抛出不明确的列引用错误。
可以让查询正常工作,然后向表中添加一列,例如将 id
列添加到 question_pot
表中,然后查询将开始失败,并出现“列不明确”错误。
以我的思维方式,向表中添加列会导致“工作”查询中断,这是 Not Acceptable 。我们可以通过显式限定列引用来防止将来出现此类错误,即使现在不需要。
至于为什么我们选择使用 q
和 r
等短别名来代替表名。
与您在评论中识别表名称的方式完全相同:
wp_ai_quiz_tblquestions (=question)
wp_ai_quiz_tblquestionpots (=pot)
wp_ai_quiz_question_pot (=question_pot)
我本质上是在用表别名说同样的事情:
wp_ai_quiz_tblquestions (=q)
wp_ai_quiz_tblquestionpots (=p)
wp_ai_quiz_question_pot (=r)
比较阅读此内容:
SELECT q.*
FROM wp_ai_quiz_tblquestions q
JOIN wp_ai_quiz_question_pot r
ON r.question_id = q.id
WHERE r.pot_id = 13
阅读本文:
SELECT wp_ai_quiz_tblquestions.*
FROM wp_ai_quiz_tblquestions
JOIN wp_ai_quiz_question_pot
ON wp_ai_quiz_question_pot.question_id = wp_ai_quiz_tblquestions.id
WHERE wp_ai_quiz_question_pot.pot_id = 13
再添加几个表格,也不要像我总是那样排列内容,这需要读者付出更多的努力来破译该语句的作用。在非常复杂的查询中,引用六个或更多表,我将在查询上方添加注释,解释别名的用法。
-- find all questions in a particular pot
-- q = question row to be returned from wp_ai_tblquestion
-- r = relationship between question and pot to be searched
SELECT q.id
, q.name
, ...
关于mysql - SQL 多对多关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30415940/