【问题标题】:Select rows from a table where row in another table with same id has a particular value in another column从表中选择行,其中具有相同 id 的另一个表中的行在另一列中具有特定值
【发布时间】:2012-02-24 16:48:06
【问题描述】:

在 MySQL 中:

如果我们有两个表:

comments
key    |    value
=================
1      |    foo
2      |    bar
3      |    foobar
4      |    barfoo

和:

meta
comment_key    |    value
=========================
1              |    1
2              |    1
3              |    2
4              |    1

我想从comment 表中获取在meta 表中具有相应comment_key 且具有特定value 的cmets(meta 表中的value 列)。

例如,我想从comment 表中选择所有在meta 表中具有value1 的行:

我希望得到这些结果:

key    |    value
=================
1      |    foo
2      |    bar
4      |    barfoo

如果我要从comment 表中选择所有在meta 表中具有value2 的行:

我希望得到这样的结果:

key    |    value
=================
3      |    foobar

真的希望有人能帮忙,提前谢谢大家!

我想我需要加入吗?任何指针都会很棒,如果可能的话,一个简短的解释,这样我就可以找出哪里出错了 -> 下次我会知道的!

【问题讨论】:

    标签: mysql sql select join


    【解决方案1】:

    我实际上不建议为此使用 JOIN — 或者更确切地说,我建议使用“semijoin”,这是一个不直接在 SQL 中表达的关系代数概念。半联接本质上是一种联接,您只想从一个表中检索记录,但条件是它们在不同的表中具有相应的记录。

    在 SQL 表示法中,这个概念是通过使用 an IN clausesubquery 间接表达的:

    SELECT key, value
      FROM comments
     WHERE key IN
            ( SELECT comment_key
                FROM meta
               WHERE value = 1
            )
    ;
    

    (MySQL 实际上最终会在内部将其转换回半连接——本质上是一种退化的内连接——但IN 子句是在原始 SQL 中表达它的自然方式。)

    【讨论】:

    • 更正 - 使用 joinexistsin 谓词无关紧要,它们都是半连接 - 定义为基于从一个表返回行的连接另一个表中存在相关行。
    • @JCooper:我不这么认为。假设对于parent 中的每条记录,child 中有零个、一个或多个记录。那么半连接将包括每个parent 记录的零个或一个副本,而SQL INNER JOIN 将包括一些parent 记录的多个副本。但我可以看到你的方式。在关系代数中,半连接相当于一个内连接,然后是一个适当的投影;因此我们可以将其视为 SQL SELECT 和关系代数投影之间的差异,而不是 SQL INNER JOIN 和关系代数半连接之间的差异。
    • 哇,我是如此接近,我只有= 而不是IN!谢谢你,工作愉快!
    • 我在使用 join 方法时遇到了完全相同的重复行问题。 join 不能解决重复行问题,感觉很奇怪。
    • 这与使用简单连接但运行 distinct 以确保其唯一性相比如何?
    【解决方案2】:

    您正在这里寻找一个普通的、普通的 equi-join。

    SELECT `comment`.`key`   AS `key`,
           `comment`.`value` AS `value`
        FROM `comments` 
            JOIN `meta` 
                ON `comments`.`key` = `meta`.`comment_key` 
        WHERE `meta`.`value` = 1;
    

    我不太确定您在这里寻找什么样的建议,但您可以在 Wikipedia's SQL JOIN page. 阅读有关该主题(不是 MySQL 特定)的更多信息

    我建议在 comment.keymeta.comment_key 上建立索引,假设您希望每个 comment 行只有 1 个 meta 行(PRIMARY根据定义,键是唯一的)。如果您希望每个 comment 允许超过 1 个 meta,则将单独的索引 id 列添加到 meta 并使其成为带有 comment_key 的主键只是一个 b 树索引。

    我也不确定它的性能与同样列出的“半连接”答案相比如何,但对我来说,这是表达查询的更简单、更自然的方式;不过,只有两个表,MySQL 优化起来应该不会太难。

    【讨论】:

    • 我不确定是否提及索引是否过度提出问题。我刚刚看到太多的程序员没有考虑它们,因为查询总是在测试数据上运行得很快,每个表有十几行或更少。
    • 如果有多个子行,这不会导致父行重复吗?
    【解决方案3】:

    我会通过以下方式使用“INNER JOIN”:

    SELECT comments.key, comments.value FROM comments 
    INNER JOIN meta ON comments.key=meta.comment_key WHERE meta.value = 1;
    

    干杯! ;-)

    【讨论】:

      猜你喜欢
      • 2013-01-02
      • 1970-01-01
      • 2017-02-14
      • 2012-05-25
      • 2019-05-31
      • 1970-01-01
      • 1970-01-01
      • 2017-12-24
      • 2022-07-18
      相关资源
      最近更新 更多