【问题标题】:Joins on MySQL many-to-many tables连接 MySQL 多对多表
【发布时间】:2011-08-23 15:13:16
【问题描述】:

这让我发疯了。

我有三张桌子:

items
  ID
  name
  type

cats
  ID
  name

items_to_cats
  FK_ITEM_ID
  FK_CAT_ID

这是一个简单的多对多关系。我有项目和类别。每个项目都可以链接到一个或多个类别。这是通过一个简单的连接表完成的,其中每一行使用外键约束维护一个项目和一个类别之间的关系。

您会注意到我的“items”表有一个名为“type”的字段。这是一个索引列,它定义了存储在那里的内容类型。此处的示例值为“report”、“interview”、“opinion”等。

问题来了。 我想检索至少包含一项“报告”类型的类别列表

理想情况下,我希望使用连接在单个查询中获得结果。救命!

【问题讨论】:

    标签: mysql database join many-to-many


    【解决方案1】:
    select distinct cats.id, cats.name
    from cats
    join items_to_cats on items_to_cats.fk_cat_id=cats.id
    join items on items.id=items_to_cats.fk_item_id
    where items.type='report'
    

    就数据库设计而言,如果您对 items.type 有一小组合法值,即“report”、“interview”、“opinion”,也许还有更多,那么您真的应该创建一个单独的例如,带有 id 和名称的表,然后只需将类型 id 放入 items 表中。这样你就不会因为某处拼写错误的“报告”而陷入麻烦,或者更有可能的是,有人把“报告”而不是“报告”。

    【讨论】:

    【解决方案2】:

    或者这个怎​​么样:

    SELECT c.id, c.name 
    FROM cats c
    WHERE c.id IN 
        (SELECT ic.fk_cat_id 
         FROM items_to_cats ic 
         JOIN items i on i.id=ic.fk_item_id 
         WHERE items.type='report'
        )
    

    【讨论】:

    • 也可以完美运行,感谢凯文。如果您有兴趣,Jay 的双连接解决方​​案实际上要快一些,但我目前仅在非常小的数据上测试了这两个查询!
    • 很有趣,我没想到里面有很多东西,我想这就是为什么查看查询计划和理解底层数据如此重要的原因。
    • 嵌入式查询通常比连接慢。我记得曾经在 Oracle 文档中阅读过 Oracle 出于性能原因尝试将嵌入式查询“扁平化”到连接中。但很高兴看到两个解决方案:它可能会为您提供如何解决其他查询问题的想法。
    • 我不确定这是真的,我希望首先评估驱动子查询,只要它的结果集相对较小,它应该更快,因为数据库应该实现 fk返回的用于查询 pk 。(我假设 fk 和类型都被索引了)....我这里没有 mysql,我稍后再检查。
    • 做了一些测试,有 200k 个项目和 90k 个 items_to_cats,(分析了所有表并且所有列索引的数据分布均等)我发现 2 个查询采用完全相同的数量MYSQL & Oracle 的时间。然而,在 Oracle 中,查询计划报告的查询成本大约要好 3 倍(DISTINCT 导致了额外的工作)。
    猜你喜欢
    • 1970-01-01
    • 2011-01-27
    • 2021-12-25
    • 2020-04-23
    • 2011-07-06
    • 1970-01-01
    相关资源
    最近更新 更多