【问题标题】:Inner joining on the same table twice in PostgreSQL query在 PostgreSQL 查询中两次内连接同一张表
【发布时间】:2020-11-05 19:51:48
【问题描述】:

我正在与我的 PostgreSQL 数据库上的以下查询搏斗,最初是使用 Doctrine Query Builder 构建的(但这与这里无关)。

我有一个名为“Course”的实体,它在“Log”表中有多个记录。

log.resumeComplete 的记录有一个日期,log.activated 的记录有一个日期。

在这个查询中,我希望提取日期早于 X 的 log.activated 和早于 Y 的 log.resumeComplete 的记录。重要的是,一些“课程”记录在日志中没有对应的 log.resumeComplete 记录表。

有没有一种方法可以让我通过一个查询来获取这些信息?

SELECT s0_.slug AS slug, s0_.status AS status, a2_.time AS resumeTime
FROM Course s0_ 
    INNER JOIN Log a1_ ON (a1_.course_id = s0_.id) 
    INNER JOIN Log a2_ ON (s0_.id = a2_.course_id AND a2_.type = 'log.resumeComplete')
WHERE s0_.status = 'active' 
    AND s0_.currentsss = '72' 
    AND a1_.type = 'log.activated'
    AND a1_.time < '2020-05-31 14:25:31'   
    AND a2_.time IS NULL OR a2_.time < '2020-07-11 14:25:31'
ORDER BY s0_.id ASC;

【问题讨论】:

  • 我不认为这可以做得更好,除非你应该尝试摆脱OR - 你可以使用coalesce,它可以被索引。
  • @LaurenzAlbe 感谢您的评论。我在这里使用OR 的尝试是因为并非每条记录都会有“resumeComplete”时间,但是当我引入IS NULL 时,查询会忽略“活动”的状态并返回我不想要的结果。您对使用coalesce 功能有何建议?
  • @LaurenzAlbe 很抱歉您不得不删除您的帖子,也许我没有清楚地解释这个问题。 :-(
  • 这是我的错和你的错,所以别担心。

标签: sql postgresql join left-join inner-join


【解决方案1】:

这个查询应该工作(不是小提琴/测试集):

改变了:

  • 内连接 => 左连接
  • 第一个连接条件上移
  • “或”适用于所有可渗透的条件,使它们无用。需要“( )”
  • 可能是隐式类型转换(时间

SQL

SELECT s0_.slug AS slug, s0_.status AS status, a2_.time AS resumeTime
FROM Course s0_ 
    INNER JOIN Log a1_ ON (a1_.course_id = s0_.id and AND a1_.type = 'log.activated')  
    left JOIN Log a2_ ON (a2_.course_id = s0_.id AND a2_.type = 'log.resumeComplete')
WHERE s0_.status = 'active' 
    AND s0_.currentsss = '72' 
    
    AND a1_.time < '2020-05-31 14:25:31'   
    AND (a2_.time IS NULL OR a2_.time < '2020-07-11 14:25:31') -- this type of comparison might cause an implicet conversion of a2_.time to varchar. bad
ORDER BY s0_.id ASC;

【讨论】: