如何在postgresql中对重叠数据进行汇总?

How to sum up the data for the overlapped data in postgresql?

我有如下数据:

t_id s_id   date_1      date_2      T_count            expected Result
N1  1-1I    2012-12-11  2013-01-22  0.21327014218009478622 4.7
N2  1-1I    2011-08-03  2011-11-10  3.8461538461538462     4.7
N3  1-1I    2013-12-05  2013-12-20  1.6935483870967742     4.7
N4  1-1I    2014-12-08  2015-06-25  4.7727272727272727     4.7
N5  1-1I    2017-03-08  (null)      (null)                 4.7
N6  1-I6    2013-04-11  2013-10-03  0.61538461538461538462 0.97
N7  1-I6    2011-09-27  2013-06-20  0.37325038880248833651 0.97

并且我想计算 t_count 值的总和,如果相同 s_id 的 date1 和 date2 与不同 t_id 的相同 s_id 重叠,否则 return 相同的最大值 s_id.

现在我正在使用的 postgres 代码正在计算值的总和而不考虑重叠,请你提出建议。

对于给定的 s_id,可能存在一些数据重叠而另一些不重叠的情况,因此对于重叠的年份,我们需要进行一些整理并找到所有情况中的最大值,例如个人,重叠并给出一个最大的答案。

select t1.s_id,sum(t1.t_count) 
              from abc t1
              JOIN abc t2
              ON daterange(t1.date_1, t1.date_2, '[]')
                             && daterange(t1.date_1, t1.date_2, '[]')
                                      and t1.s_id = t2.s_id
              GROUP BY t1.s_id

不清楚如果某个 s_id 的某些间隔重叠而某些不重叠,逻辑应该如何工作。

如果您知道在您的数据中要么所有区间重叠,要么 none 重叠,那么就很容易确定它。

计算每个间隔的持续时间并将所有这些持续时间相加。将它与从第一个日期到最后一个日期的持续时间进行比较。

我假设 date_2 中的 NULL 表示未来某个非常大的日期。

WITH
CTE
AS
(
    SELECT
        s_id
        ,SUM(COALESCE(date_2, '9999-12-31') - date_1) AS TotalDuration
        ,MIN(date_1) AS FirstDate
        ,MAX(COALESCE(date_2, '9999-12-31')) AS LastDate
        ,SUM(T_count) AS SumCount
        ,MAX(T_count) AS MaxCount
    FROM YourTable
    GROUP BY s_id
)
SELECT
    s_id
    ,CASE WHEN TotalDuration > (LastDate - FirstDate)
    THEN -- intervals overlap
        SumCount
    ELSE -- none of the intervals overlap
        MaxCount
    END AS Result
FROM CTE
;

我犯了一个与自身比较的错误,我稍微修改了代码得到了这个结果。

with cte as
(

    select t1.s_id,sum(t1.t_count) as scount
                  from abc t1
                  JOIN abc t2
                  ON daterange(t1.date_1, t1.date_2, '[]')
                                 && daterange(t1.date_1, t1.date_2, '[]')
                                          and t1.s_id = t2.s_id
                  and t1.s_id ! = t2.s_id
                  GROUP BY t1.s_id
) 
select 
      s_id,greatest(scount,max(t_count) over (partition by s_id)) as finalvalue 
from abc 
left outer join cte 
on abc.s_id = cte.s_id