代码之家  ›  专栏  ›  技术社区  ›  SRobertJames

计算由另一个字段上定义的窗口过滤的字段的总和

  •  0
  • SRobertJames  · 技术社区  · 11 年前

    我有桌子 event :

    event_date,
    num_events,
    site_id
    

    我可以很容易地使用聚合SQL SELECT SUM(num_events) GROUP BY site_id .

    但我还有另一张桌子 site :

    site_id,
    target_date
    

    我想做一个JOIN,显示 num_events 在 target_date 、90天、120天等。我认为这可以使用 WHERE 子句。然而,这一点因两个挑战而变得复杂:

    1. 这个 目标日期 不是固定的,但各不相同 site_id
    2. 我希望在同一个表中输出多个日期范围;所以我不能做简单的 哪里 从 事件 桌子

    我想到的一个解决方法是简单地进行几个查询,每个日期范围一个,然后使用视图将它们粘贴在一起。有没有更简单、更好或更优雅的方式来实现我的目标?

    2 回复  |  直到 11 年前
        1
  •  0
  •   Gordon Linoff    11 年前

    您可以执行以下操作:

    select sum(case when target_date - event_date < 30 then 1 else 0 end) as within_030,
           sum(case when target_date - event_date < 60 then 1 else 0 end) as within_060,
           sum(case when target_date - event_date < 90 then 1 else 0 end) as within_090    
    from event e join
         site s
         on e.site_id = s.site_id;
    

    也就是说,您可以使用条件聚合。我不知道“60天内”是什么意思。这会在目标日期前几天,但类似的逻辑将适用于您的需要。

        2
  •  0
  •   Community Mohan Dere    9 年前

    在Postgres 9.4中,使用 new aggregate FILTER clause :

    假设实际值 date 数据类型,因此我们可以简单地进行加法/减法 integer 天数。
    将“n天内”解释为“+/-n天”:

    SELECT site_id, s.target_date
         , sum(e.num_events) FILTER (WHERE e.event_date BETWEEN s.target_date - 30
                                                 AND s.target_date + 30) AS sum_30
         , sum(e.num_events) FILTER (WHERE e.event_date BETWEEN s.target_date - 60
                                                 AND s.target_date + 60) AS sum_60
         , sum(e.num_events) FILTER (WHERE e.event_date BETWEEN s.target_date - 90
                                                 AND s.target_date + 90) AS sum_90
    FROM   site  s
    JOIN   event e USING (site_id)
    WHERE   e.event_date BETWEEN s.target_date - 90
                             AND s.target_date + 90
    GROUP  BY 1, 2;
    

    还将条件添加为 WHERE 子句以尽早排除不相关的行。如果超出范围的行数不多,这应该会大大加快 sum_90 在里面 event .