繁体   English   中英

Postgres LEFT JOIN 与 WHERE 条件

[英]Postgres LEFT JOIN with WHERE condition

我需要左加入两个带有 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

left join 两个带有 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;

正如所评论的,在结果中包含来自time_table的列是有意义的,但这是我的可选添加。

您还需要清楚下限和上限 一般约定是在时间( timestamp )范围内包括下限并排除上限。 因此我在上面使用>=<

有关的:

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

我不确定这是否是你想要的,但如果你说你想要 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

也就是说,对于大型数据集,这将是非常低效的。 如果您的数据相对较小(每个表中 < 10k 条记录,后过滤器),那么它可能并不重要,但如果您需要扩展这个概念,则需要更多地了解您的数据 - 例如,做日期,总是四舍五入到每个月的第一天?

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

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)       

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM