mysql - SQL 多对多关系

标签 mysql wordpress join

我正在使用 Wordpress 测验插件。它有两个表(实际上更多,但我试图专注于这个问题)——“questions”和“questionpots”:

‘questions’: QuestionID ---- Question ---- potID

‘questionpots’: potID ---- potName

默认查询是: $SQL = '从问题中选择 * WHERE potID='.$potID;

因此,默认情况下,每个问题都分配给一个特定的池(“问题”表中的“potID”),并且关系是“一对多”。我想做的是将问题分配给多个 jar ,例如“罗马何时沦陷?”的问题。会被问到是否有人选择“罗马历史”锅或“古代历史”锅。

所以我添加了第三个表“relations”,它匹配 QuestionID 和 potID。 问题是我无法弄清楚从“questions”WHERE potID='.$potID 中选择 * 的查询,假设 $potID 有一个或多个问题。

我应该如何加入这个表? 谢谢。

最佳答案

为了解决两个实体之间的多对多关系,我们添加第三个表,即关系表,其中外键引用两个实体表。

添加到关系表中的一行代表两个实体之间的(等等...)关系

举个例子,假设表 questionpot 都有一个 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=7pot 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 是否是对 questionquestion_pot 中的列的引用。 (如果此查询位于 MySQL 存储程序(过程、函数、触发器)中,则对 id 的引用是对列的引用,还是对过程变量的引用。)

在某些情况下,当引用可以引用多个表中的列时,我们必须限定列引用以使引用明确,并导致 MySQL 抛出不明确的列引用错误。

可以让查询正常工作,然后向表中添加一列,例如将 id 列添加到 question_pot 表中,然后查询将开始失败,并出现“列不明确”错误。

以我的思维方式,向表中添加列会导致“工作”查询中断,这是 Not Acceptable 。我们可以通过显式限定列引用来防止将来出现此类错误,即使现在不需要。

至于为什么我们选择使用 qr 等短别名来代替表名。

与您在评论中识别表名称的方式完全相同:

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/

相关文章:

MySQL 添加 (num) 到 smallint 列

wordpress - Woocommerce 产品查询 - order_by

mysql - 从一个表中选择行,仅连接另一个表的一行

python - 如何在一列和一个索引上连接两个 Pandas 数据框

mysql - 加入来自同一个表的三个查询

php - 使用 PHP 创建购物篮

mysql - 仅当表更新时触发

mysql - 连接两个选择的结果 - mysql

css - Wordpress 分页数

css - 我可以去除 CSS 文件的所有内容吗?