You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

迁移查询至Ecto时,如何实现PostgreSQL默认LEFT JOIN(LEFT INNER JOIN)效果以过滤匿名帖子

解决Ecto中获取非匿名帖子的查询问题

嘿,先帮你理清一个容易混淆的概念:在PostgreSQL里,LEFT JOIN和LEFT OUTER JOIN是完全等价的——你写的原生SQL其实也会返回匿名帖子,这并不是Ecto的问题,而是对SQL连接类型的理解偏差。你想要的“仅包含非匿名帖子”的需求,其实需要的是内连接(INNER JOIN),而不是左连接。

正确的Ecto查询写法

Ecto中默认的join:操作就是INNER JOIN,刚好匹配你的需求。把left_join:换成join:即可:

nonanonymous_posts = from p in Post,
  join: u in User,
  on: p.creator_id == u.id,
  select: %{
    id: p.id,
    title: p.title,
    body: p.body,
    creator_name: u.name,
    creator_avatar: u.avatar
  }

这个查询生成的SQL会是标准的INNER JOIN,只会返回那些存在对应创作者(creator_id有效且关联到users表记录)的帖子,自动排除匿名帖子。

为什么你的原写法不对?

你之前用left_join:时,Ecto生成的LEFT OUTER JOIN会保留posts表的所有记录——包括creator_id为NULL或者在users表中找不到匹配的匿名帖子,这就是结果里出现不需要内容的原因。

补充:如果一定要用左连接但过滤无匹配记录

如果你出于某些原因必须用左连接,但又要排除没有对应创作者的帖子,可以在查询里加上where条件过滤掉users表字段为NULL的记录:

nonanonymous_posts = from p in Post,
  left_join: u in User,
  on: p.creator_id == u.id,
  where: not is_nil(u.id),
  select: %{
    id: p.id,
    title: p.title,
    body: p.body,
    creator_name: u.name,
    creator_avatar: u.avatar
  }

不过这种写法和直接用INNER JOIN效果完全一致,而且INNER JOIN的语义更贴合你的需求,可读性也更强,所以更推荐第一种写法。

内容的提问来源于stack exchange,提问作者user13528444

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 17:44:05