【问题标题】:Postgres Left Join with where conditionPostgres Left Join with where 条件
【发布时间】:2017-03-20 19:13:54
【问题描述】:

我需要左连接两个带有 where 条件的表:

time_table
id     rid        start_date                end_date
1       2     2017-07-01 00:00:00     2018-11-01 00:00:00
2       5     2017-01-01 00:00:00     2017-06-01 00:00:00
3       2     2018-07-01 00:00:00     2020-11-01 00:00:00
record_table
id      name                 date
1      record1       2017-10-01 00:00:00
2      record2       2017-02-01 00:00:00
3      record3       2017-10-01 00:00:00

我需要获取在给定日期范围内存在的所有记录。在上面的示例中,我只需要那些位于rid = 2 范围内的记录。因此,上述查询的输出需要是:

1      record1       2017-10-01 00:00:00    
3      record3       2017-10-01 00:00:00

【问题讨论】:

  • 你试过什么?请发布一些示例代码和输出,并告诉我们什么不适合您。另外,请查看此链接:stackoverflow.com/help/mcve。
  • 你用的是postgresql还是mysql?
  • 您的输出示例不需要问题标题中的外连接。这是一个内部连接。
  • @ClodoaldoNeto:LEFT JOIN 可以显示来自time_table 的行(或选定的列)与rid = 2 匹配,即使record_table 中没有行与时间重叠范围。否则,如果用户得到一个空结果(没有行),并且(s)他无法判断time_table(没有rid = 2)或record_table中是否没有匹配项。当然,在结果中包含start_dateend_date 是有意义的,或者你只是得到后一种情况的一行NULL 值——这仍然很重要。
  • @ErwinBrandstetter:虽然可以使查询完成,但发布的输出示例并没有给出提示。 OP 提到了left join,但这可能只是一些误解。在没有他的澄清的情况下,我倾向于更加重视所需的输出。我上面的评论是呼吁澄清,我应该说清楚。但恭喜您始终提供详细的答案。

标签: mysql sql postgresql left-join date-range


【解决方案1】:
SELECT time_tbl.name,record_tbl.date 
FROM dbo.time_table AS time_tbl
     INNER JOIN record_table AS record_tbl
           ON time_tbl.id=record_tbl.id
WHERE(time_tbl.rid=2)       

【讨论】:

  • 这在几乎所有方面都是不正确的。错误的 JOIN、错误的条件、错误的结果列。这可能发生,但最重要的是:根本没有解释。
【解决方案2】:

我不确定这是否是你想要的,但如果你说你想要 record_table 日期在 time_table 中的日期之间的日期,那么这可以完成工作:

select
  rt.id, rt.name, rt.date
from
  time_table tt
  join record_table rt on
    rt.date between tt.start_date and tt.end_date
where
  tt.rid = 2

也就是说,对于大型数据集,这将是非常低效的。如果您的数据相对较小(每个表中

同样,从您的示例中,我不确定这是否是您所说的“获取所有在给定日期范围内存在的记录”的意思。

【讨论】:

    【解决方案3】:

    用 where 条件左连接两个表

    通常错误使用LEFT [OUTER] JOIN,然后使用WHERE 条件进行过滤,从而使LEFT JOIN 的特殊功能无效,以包含左表中的所有行无条件。详细解释:

    将应该过滤所有行的条件放入WHERE 子句 (rid = 2),但将来自 record_table 的左连接行的条件设为实际连接条件:

    SELECT t.start_date, t.end_date  -- adding those
         , r.id, r.name, r.date 
    FROM   time_table t
    LEFT   JOIN record_table r ON r.date >= t.start_date
                              AND r.date <  t.end_date
    WHERE  t.rid = 2;
    

    As commented,在结果中包含来自time_table 的列是有意义的,但这是我的可选添加。

    您还需要清楚上下限。一般约定是包括时间范围的下限和排除时间上限(timestamp)。因此我在上面使用了&gt;=&lt;

    相关:

    使用正确的索引,性能应该完全没有问题。 您需要在 time_table(rid)record_table(date) 上创建一个索引(或 PK)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-28
      • 1970-01-01
      • 1970-01-01
      • 2019-12-27
      • 2021-02-15
      • 2017-07-31
      相关资源
      最近更新 更多