【问题标题】:Oracle agregate by ID with time rangeOracle 按时间范围按 ID 聚合
【发布时间】:2021-02-18 10:39:27
【问题描述】:

我确定我在某处看到它,但我找不到它。 鉴于此表历史性:

ID1 ID2 Event_Date Label
1 1 2020-01-01 1
1 1 2020-01-02 1
1 1 2020-01-04 1
1 1 2020-01-08 1
1 1 2020-01-20 1
1 1 2020-12-30 1
1 1 2020-01-01 0
1 1 2020-01-02 1
1 1 2020-01-04 0
1 1 2020-01-08 1
1 1 2020-01-20 0
1 1 2020-12-30 1
1 2 2020-01-01 1
1 2 2020-01-02 1
1 2 2020-01-04 1
2 1 2020-01-08 1
2 1 2020-01-20 1
2 1 2020-12-30 1

以及表格起点

ID1 ID2 Event_Date
1 1 2020-01-01
1 1 2020-01-02
1 1 2020-01-05
1 1 2020-01-08
1 1 2020-01-21
1 1 2021-01-01
1 1 2020-01-01
1 1 2020-01-03
1 1 2020-01-06
1 1 2020-01-11
1 1 2020-01-20
1 1 2020-12-31
1 2 2020-01-03
1 2 2020-01-05
1 2 2020-01-08
2 1 2020-01-08
2 1 2020-01-21
2 1 2021-01-01

对于起始点中的每一行,计算历史记录中具有相同 ID1 和 ID2 的行数,其中历史记录中的 Event_Date 介于 StartingPoint.Event_date - n 天之间(我将其设为 n 以便我可以更改不同的值)和StartingPoint.Event_date - 2 天。然后使用相同的规则计算 label = 1 的行的分数。

我知道我可以用 join 来做到这一点,但是如果历史和起点非常大,这看起来效率很低(对于起点中的每一行,它都会创建一个大的连接,最后它会汇总相同的集合行多次重复)。从抽象的角度来看,在我看来,最好先汇总每个 ID1、ID2、Event_date 的历史记录,并与起点连接并选择最佳的,但我对其他解决方案持开放态度。

【问题讨论】:

  • 你必须加入他们,所以不太清楚你的意思。如果您有一些可行但您认为效率低下的东西(以及您为什么这么认为),则包含您对此数据的期望结果和当前查询可能会有所帮助。

标签: sql oracle join aggregate


【解决方案1】:

您可以使用子查询尝试以下解决方案:

select * ,(select count(*) from historic h where h.id1=s.id1 and h.id2=s.id2 and h.event_date between dateadd(day,-30,s.event_date) and dateadd(day,-2,s.event_date) )from startingpoint  s

【讨论】:

    【解决方案2】:

    你必须有某种形式的加入;要么直接加入,要么使用标量子查询,这可能不会那么有效。

    如果您只想查看具有历史数据的行,最简单的方法可能只是简单的连接:

    select sp.id1, sp.id2, sp.event_date,
      count(h.event_date) as any_label,
      count(case when h.label = 1 then h.label end) as label_1,
      count(case when h.label = 1 then h.label end) / count(h.event_date) as fraction_1
    from startingpoint sp
    join historic h on h.id1 = sp.id1
    and h.id2 = sp.id2
    and h.event_date >= sp.event_date - 10
    and h.event_date < sp.event_date - 2
    group by sp.id1, sp.id2, sp.event_date
    order by sp.id1, sp.id2, sp.event_date;
    

    其中 n 为 10;你的数据会给你:

    ID1 ID2 EVENT_DATE ANY_LABEL LABEL_1           FRACTION_1
    --- --- ---------- --------- ------- --------------------
      1   1 2020-01-05         4       3                  .75
      1   1 2020-01-06         4       3                  .75
      1   1 2020-01-08         6       4 .6666666666666666667
      1   1 2020-01-11         8       6                  .75
      1   2 2020-01-05         2       2                    1
      1   2 2020-01-08         3       3                    1
    

    或者如果你想看到零计数,你可以使用外连接;但是分数计算需要一些逻辑来避免被零除的错误:

    select sp.id1, sp.id2, sp.event_date,
      count(h.event_date) as any_label,
      count(case when h.label = 1 then h.label end) as label_1,
      case when count(h.event_date) > 0 then
        count(case when h.label = 1 then h.label end) / count(h.event_date)
      end as fraction_1
    from startingpoint sp
    left join historic h on h.id1 = sp.id1
    and h.id2 = sp.id2
    and h.event_date >= sp.event_date - 10
    and h.event_date < sp.event_date - 2
    group by sp.id1, sp.id2, sp.event_date
    order by sp.id1, sp.id2, sp.event_date;
    

    得到:

    ID1 ID2 EVENT_DATE ANY_LABEL LABEL_1           FRACTION_1
    --- --- ---------- --------- ------- --------------------
      1   1 2020-01-01         0       0
      1   1 2020-01-02         0       0
      1   1 2020-01-03         0       0
      1   1 2020-01-05         4       3                  .75
      1   1 2020-01-06         4       3                  .75
      1   1 2020-01-08         6       4 .6666666666666666667
      1   1 2020-01-11         8       6                  .75
      1   1 2020-01-20         0       0
      1   1 2020-01-21         0       0
      1   1 2020-12-31         0       0
      1   1 2021-01-01         0       0
      1   2 2020-01-03         0       0
      1   2 2020-01-05         2       2                    1
      1   2 2020-01-08         3       3                    1
      2   1 2020-01-08         0       0
      2   1 2020-01-21         0       0
      2   1 2021-01-01         0       0
    

    db<>fiddle

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-20
      • 1970-01-01
      • 2012-09-18
      • 2020-07-01
      • 1970-01-01
      • 2014-03-09
      • 2020-03-22
      相关资源
      最近更新 更多