简体   繁体   English

Postgres LEFT JOIN 与 WHERE 条件

[英]Postgres LEFT JOIN with WHERE condition

I need to left join two tables with a where condition:我需要左加入两个带有 where 条件的表:

Table time_tabletime_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

Table record_tablerecord_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

I need to get all those records which are present under given date range.我需要获取在给定日期范围内存在的所有记录。 In the above example, I need those records that lie under range for rid = 2 only.在上面的示例中,我只需要那些在rid = 2范围内的记录。 Hence the output for the above query needs to be:因此,上述查询的输出需要是:

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

left join two tables with a where condition left join 两个带有 where 条件的表

It's typically wrong to use a LEFT [OUTER] JOIN and then filter with a WHERE condition, thereby voiding the special feature of a LEFT JOIN to include all rows from the left table unconditionally .使用LEFT [OUTER] JOIN然后使用WHERE条件进行过滤通常是错误的,从而使LEFT JOIN的特殊功能无效,即无条件地包含左表中的所有行。 Detailed explanation:详细解释:

Put conditions supposed to filter all rows into the WHERE clause ( rid = 2 ), but make conditions to left-join rows from record_table out to be actual join conditions:将应该过滤所有行的条件放入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 , it makes sense to include columns from time_table in the result, but that's my optional addition. 正如所评论的,在结果中包含来自time_table的列是有意义的,但这是我的可选添加。

You also need to be clear about lower and upper bounds .您还需要清楚下限和上限 The general convention is to include the lower and exclude the upper bound in time ( timestamp ) ranges.一般约定是在时间( timestamp )范围内包括下限并排除上限。 Hence my use of >= and < above.因此我在上面使用>=<

Related:有关的:

Performance should be no problem at all with the right indexes.使用正确的索引,性能应该完全没有问题 You need an index (or PK) on time_table(rid) and another on record_table(date) .您需要time_table(rid)上的索引(或 PK)和 record_table( record_table(date)上的另一个索引。

I'm not exactly sure if this is what you want, but if you are saying you want the dates where the record_table date is between the dates in the time_table, then this would do the job:我不确定这是否是你想要的,但如果你说你想要 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

That said, this will be horribly inefficient for large datasets.也就是说,对于大型数据集,这将是非常低效的。 If your data is relatively small (< 10k records in each table, post-filters), then it probably won't matter much, but if you would need to scale this concept, it would warrant knowing more about your data -- for example, do the dates, always round to the first of each month?如果您的数据相对较小(每个表中 < 10k 条记录,后过滤器),那么它可能并不重要,但如果您需要扩展这个概念,则需要更多地了解您的数据 - 例如,做日期,总是四舍五入到每个月的第一天?

Again, from your example, I wasn't sure if this is what you meant by "get all those records which are present under given date range."同样,从您的示例中,我不确定这是否是您所说的“获取在给定日期范围内存在的所有记录”的意思。

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