如何查询多对多
Posted
技术标签:
【中文标题】如何查询多对多【英文标题】:How to query many to many 【发布时间】:2010-06-29 00:43:09 【问题描述】:我正在尝试对这些字段进行多对多查询。我想得到:
1) 属于某个类别的所有帖子
2) 帖子中的所有类别
3) 属于某个类别且具有特定 ID 的所有帖子
posts
+-------------+--------------+
| id | int(11) |
| title | varchar(255) |
| body | text |
| parent_id | int(11) |
| category_id | int(11) |
+-------------+--------------+
post_categories
+----------+--------------+
| id | int(11) |
| category | varchar(255) |
+----------+--------------+
post_category_bridge
+-------------+-------------+
| id | int(11) |
| post_id | int(11) |
| category_id | int(11) |
+-------------+-------------+
我担心的一件事是,我在 mysql DB 上使用 php 的 PDO 进行开发,但我将在发布当天将该站点转移到 SQL Server。我知道 MySQL 和 SQL Server 之间存在差异。 POD 会处理这些差异,还是我需要重新编写这些查询。
提前致谢。
【问题讨论】:
为什么post.id
是int(11)
而post_category_bridge.post_id
是tinyint(11)
?这在创建外键时很常见吗?
posts 表中不需要您的 category_id。这应该是您的“桥梁”或关系表的目的。
【参考方案1】:
我使用详细的连接语法来更清楚地了解表的相关性。
1) 属于某个类别的所有帖子
给定类别名称,您需要连接所有三个表。
select p.*
from post_category c
join post_category_bridge b on c.id = b.category_id
join posts p on p.id = b.post_id
where c.category = ?
2) 帖子中的所有类别
给定post id,你只需要加入bridge和category表。
select c.*
from post_category_bridge b
join post_category c on c.id = b.category_id
where b.post_id = ?
3) 属于某个类别且具有特定 ID 的所有帖子
我认为您的意思是在这里查找category.id
的帖子(而不是category.name
),这类似于(1)但不需要加入类别表,因为您已经知道 id;您只需要加入 bridge 和 post 表。
select p.*
from post_category_bridge b
join posts on p.id = b.post_id
where b.category_id = ?
我将在发布当天将网站转移到 SQL Server...POD 会处理这些差异还是需要重新编写这些查询。
这取决于最终出现在您系统中的查询。如果您正在编写自己的 SQL,那么在开发过程中是否使用 MySQL 独有的功能或语法将很重要。我强烈建议在 SQL Server 很久之前 发布日进行测试,否则您可能会发现发布推迟了一段时间。您可以为此免费下载evaluation version。
cmets中提到的重复点:
正如@freddy 提到的,您不需要posts.category_id
字段。在多对多关系中,桥(又名“junction”、“join”、“map”、“link”等)表将帖子链接到多个类别 - posts
表上的单个字段将被使用,如果只允许一个类别。
正如@JamieWong 提到的,您应该保持表键和外键之间的类型一致,例如如果posts.id
是int(11)
,那么post_category_bridge.post_id
也应该是int(11)
。大多数(全部?)强制外键约束的数据库都需要这个(包括 MySQL)。为什么?如果可以有 4294967295 个帖子(由 4 字节 int
支持),那么桥表中的意义不大,只支持链接到 255 个帖子(由 1 字节 tinyint
支持)
当你在做这件事时……不妨将 ID(以及这些 ID 的 FK)设为unsigned
。
【讨论】:
【参考方案2】:这有帮助吗?
1:
select p.* from posts p, post_categories c
where p.category_id=c.id and category='something'
2:
select c.* from post_categories, posts p
where p.category_id=c.id and post_id=something
3:
select p.* from post_categories, posts p
where p.category_id=c.id and post_id=something and category='something'
【讨论】:
【参考方案3】:
select a.* from posts a, post_categories b, post_category_bridge c
WHERE
b.category="mycat" AND
b.id=c.category_id AND
a.id = c.post_id;
select b.category from posts a, post_categories b, post_category_bridge c,
WHERE
c.post_id='PostID' AND
b.id = c.category_id;
select a.* from posts a, post_categories b, post_category_bridge c
WHERE
b.category="mycat" AND
c.category_id = b.id AND
c.post_id = 'MyID' AND
a.id = c.post_id;
【讨论】:
以上是关于如何查询多对多的主要内容,如果未能解决你的问题,请参考以下文章
Laravel:如何在多态多对多中使用 wherePivot