mysql - 我可以选择在 MySQL 中加入哪些行吗

标签 mysql join

假设我有两个表,peopleemailsemails 有一个 person_id、一个 address 和一个 is_primary:

people:
  id

emails:
  person_id
  address
  is_primary

要获取每个人的所有电子邮件地址,我可以做一个简单的连接:

select * from people join emails on people.id = emails.person_id

如果左表中的每一行我只想(最多)右表中的一行怎么办?而且,如果一个人有多封电子邮件,其中一封被标记为 is_primary,有没有办法在加入时选择使用哪一行?

所以,如果我有

people:     emails:
------      -----------------------------------------
| id |      | id | person_id | address | is_primary |
------      -----------------------------------------
|  1 |      |  1 |         1 |  a@b.c  |    true    |
|  2 |      |  2 |         1 |  b@b.c  |    false   |
|  3 |      |  3 |         2 |  c@b.c  |    true    |
|  4 |      |  4 |         4 |  d@b.c  |    false   |
------      -----------------------------------------

有没有办法得到这个结果:

------------------------------------------------
| people.id | emails.id | address | is_primary |
------------------------------------------------
|         1 |         1 |  a@b.c  |    true    |
|         2 |         3 |  c@b.c  |    true    | // chosen over b@b.c because it's primary
|         3 |      null |  null   |    null    | // no email for person 3
|         4 |         4 |  d@b.c  |    false   | // no primary email for person 4
------------------------------------------------

最佳答案

你搞错了,左/右连接是如何工作的。

这个加入

select * from people join emails on people.id = emails.person_id

将为您获取两个表中符合您的 ON 条件的所有记录的每一列。

左连接

select * from people left join emails on people.id = emails.person_id

将为您提供来自人的每条记录,无论电子邮件中是否有相应的记录。如果没有,电子邮件表中的列将只是 NULL

如果一个人有多个电子邮件,则此人的结果中将有多个记录。初学者常常想知道为什么数据会重复。

如果您想将数据限制在 is_primary 的值为 1 的行中,您可以在 WHERE 子句中这样做您正在进行内部联接(您的第一个查询,尽管您省略了 inner 关键字)。

当你有一个左/右连接查询时,你必须把这个过滤器放在 ON 子句中。如果将它放在 WHERE 子句中,您会将左/右连接隐式转换为内部连接,因为 WHERE 子句会过滤 NULL 我上面提到的行。或者您可以这样编写查询:

select * from people left join emails on people.id = emails.person_id
where (emails.is_primary = 1 or emails.is_primary is null)

澄清后编辑:

Paul Spiegel 的回答很好,因此我投赞成票,但我不确定它是否表现良好,因为它有一个依赖子查询。所以我创建了这个查询。不过,这可能取决于您的数据。尝试这两个答案。

select 
p.*,
coalesce(e1.address, e2.address) AS address
from people p
left join emails e1 on p.id = e1.person_id and e1.is_primary = 1 
left join (
    select person_id, address 
    from emails e 
    where id = (select min(id) from emails where emails.is_primary = 0 and emails.person_id = e.person_id)
) e2 on p.id = e2.person_id

关于mysql - 我可以选择在 MySQL 中加入哪些行吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37263711/

相关文章:

mysql - 表之间的随机 MySQL 问题

java - 如何创建 session 以及如何使用 session 在jsp中从mysql数据库获取数据?

Mysql查询优化,搜索记录!

hadoop - Hive 加入 2 个表,一个有分区,另一个没有

如果不存在或者值等于0则mysql左连接

java - 从其他电脑连接到本地Mysql服务器

php - Laravel onDelete 级联多对多关系

html - 如何在EJS中的表中的特定单元格中排列数据

mysql - 将内部连接转换为左侧连接

mysql - MySQL 5 使用 JOIN 和 UNION 时出错