【问题标题】: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.idint(11)post_category_bridge.post_idtinyint(11)?这在创建外键时很常见吗?
  • posts 表中不需要您的 category_id。这应该是您的“桥梁”或关系表的目的。

标签: php sql mysql sql-server-2008 pdo


【解决方案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.idint(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;
      

      【讨论】:

        猜你喜欢
        • 2010-10-24
        • 2017-04-03
        • 2011-08-21
        • 1970-01-01
        • 2013-08-28
        • 1970-01-01
        • 2019-12-23
        • 2016-12-15
        相关资源
        最近更新 更多