简体   繁体   English

Postgresql left join date_trunc 使用默认值

[英]Postgresql left join date_trunc with default values

I have 3 tables which I'm querying to get the data based on different conditions.我有 3 个表,我正在查询这些表以根据不同的条件获取数据。 I have from and to params and these are the ones I'm using to create a range of time in which I'm looking for the data in those tables.我有fromto参数,这些是我用来创建时间范围的参数,我在这些时间范围内查找这些表中的数据。

For instance if I have from equals to '2020-07-01' and to equals to '2020-08-01' I'm expecting to receive the grouped row values of the tables by week, if in some case some of the weeks don't have records I want to return 0, if some tables have records for the same week, I'd like to sum them.例如,如果我from等于“2020-07-01” to等于“2020-08-01”,我希望按周收到表格的分组行值,如果在某些情况下是几周没有记录我想返回 0,如果某些表有同一周的记录,我想对它们求和。

Currently I have this:目前我有这个:

SELECT d.day, COALESCE(t.total, 0)
FROM  (
  SELECT day::date
  FROM generate_series(timestamp '2020-07-01',
                       timestamp '2020-08-01',
                       interval  '1 week') day
) d
LEFT JOIN (
  SELECT date AS day,
         SUM(total)
  FROM table1
  WHERE id = '1'
  AND date BETWEEN '2020-07-01' AND '2020-08-01'
  GROUP  BY day
) t USING (day)
ORDER BY d.day;

I'm generating a series of dates grouped by week, and on top of that I'm doing adding a left join.我正在生成一系列按周分组的日期,最重要的是我正在添加一个左连接。 Now for some reason, it only works if the dates match completely, otherwise COALESCE(t.total, 0) returns 0 even if in that week the SUM(total) is not 0.现在出于某种原因,它仅在日期完全匹配时才有效,否则COALESCE(t.total, 0)返回 0,即使在那一周 SUM(total) 不为 0。

The same way I'm applying the LEFT JOIN, I'm using other left joins with other tables in the same query, so I'm falling with the same problem.与我应用 LEFT JOIN 的方式相同,我在同一查询中使用其他左连接与其他表,所以我遇到了同样的问题。

Please see if this works for you.请查看这是否适合您。 Whenever you find yourself aggregating more than once, ask yourself whether it is necessary.每当你发现自己聚集不止一次时,问问自己是否有必要。

Rather than try to match on discrete days, use time ranges.与其尝试在离散的日期进行匹配,不如使用时间范围。

with limits as (
  select '2020-07-01'::timestamp as dt_start, 
         '2020-08-01'::timestamp as dt_end
), weeks as (
  SELECT x.day::date as day, least(x.day::date + 7, dt_end::date) as day_end
    FROM limits l
         CROSS JOIN LATERAL 
           generate_series(l.dt_start, l.dt_end, interval '1 week') as x(day)
   WHERE x.day::date != least(x.day::date + 7, dt_end::date)
), t1 as (
  select w.day, 
         sum(coalesce(t.total, 0)) as t1total
    from weeks w
         left join table1 t
                on t.id = 1
               and t.date >= w.day 
               and t.date < w.day_end
   group by w.day
), t2 as (
  select w.day, 
         sum(coalesce(t.sum_measure, 0)) as t2total
    from weeks w
         left join table2 t
                on t.something = 'whatever'
               and t.date >= w.day 
               and t.date < w.day_end
   group by w.day
)
select t1.day,
       t1.t1total,
       t2.t2total
  from t1
  join t2 on t2.day = t1.day;

You can keep adding tables like that with CTEs.您可以像使用 CTE 一样继续添加表格。

My earlier example with multiple left join was bad because it blows out the rows due to a lack of join conditions between the left-joined tables.我之前使用多个left join的示例很糟糕,因为它由于左连接表之间缺少连接条件而爆破了行。

There is an interesting corner case for eg 2019-02-01 to 2019-03-01 which returns an empty interval as the last week.有一个有趣的极端情况,例如2019-02-012019-03-01 ,它返回一个空间隔作为上周。 I have updated to filter that out.我已经更新以过滤掉它。

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

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