从表中选择行,其中具有相同 id 的另一个表中的行在另一列中具有特定值

Posted

技术标签:

【中文标题】从表中选择行,其中具有相同 id 的另一个表中的行在另一列中具有特定值【英文标题】:Select rows from a table where row in another table with same id has a particular value in another column 【发布时间】: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

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

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

【问题讨论】:

【参考方案1】:

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

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

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;

干杯! ;-)

【讨论】:

以上是关于从表中选择行,其中具有相同 id 的另一个表中的行在另一列中具有特定值的主要内容,如果未能解决你的问题,请参考以下文章

从表中选择具有最大日期的行

用于从表中选择具有最新时间戳的行的 JOOQ 代码

如果存在则从表中选择,否则从oracle中的另一个表中选择

SQL 选择由 Ids 标识并由另一个表中的特定类型过滤的行列表中的所有第一项

使用其他行的数据更新同一表中的行 SQL

如何从没有关系laravel 8的另一个表中检索具有多行的行数据