【问题标题】:SQL (bigquery) - SUM continues values with start/stop DATETIME within time intervalSQL (bigquery) - SUM 在时间间隔内以开始/停止 DATETIME 继续值
【发布时间】:2021-04-07 14:42:30
【问题描述】:

鉴于以下表 1 表示以稳定的速率持续给药:

row id starttime endtime drug_total_amount
1 21 2163-04-13T03:00:00 2163-04-13T06:00:00 99
2 21 2163-04-13T16:00:00 2163-04-13T23:00:00 540
3 21 2163-04-14T02:30:00 2163-04-14T17:00:00 308
4 21 2163-04-14T17:00:00 2163-04-14T20:30:00 72
5 21 2163-04-14T20:40:00 2163-04-15T00:00:00 40
6 6 2163-04-14T17:00:00 2163-04-14T20:30:00 72
7 6 2163-04-14T20:40:00 2163-04-15T00:00:00 39.75
8 6 2163-04-15T00:00:00 2163-04-15T01:00:00 13.5
9 6 2163-04-15T01:00:00 2163-04-15T02:00:00 9

表2代表了带有时间戳的事件:

row id event event_time
1 21 1 2163-04-14T17:30:00

在事件之前的给定时间间隔内,将管理值与特定 ID 相加的最有效方法是什么?


例如: 我想在事件 id 1 (pre_24_hours_drug) 之前的 24 小时内汇总药物量 - 表 1 中的相关行是 2-4(每个 id 和时间范围):

  1. 仅 17:00 到 endtime (~424) 之间的部分金额
  2. 总量 (308)
  3. starttime 和 17:00 (~10) 之间的部分金额

结果应该是:

row id event event_time pre_24_hours_drug
1 21 1 2163-04-14T17:30:00 742.5714286

【问题讨论】:

    标签: sql datetime select google-bigquery sum


    【解决方案1】:

    以下是 BigQuery 标准 SQL

    #standardSQL
    select t2.id, t2.event, t2.event_time,
      sum(t1.drug_total_amount 
        / timestamp_diff(t1.endtime, t1.starttime, second) 
        * timestamp_diff(
          least(t2.event_time, t1.endtime),
          greatest(timestamp_sub(t2.event_time, interval 24 hour), t1.starttime),
          second)
      ) as pre_24_hours_drug
    from `project.dataset.table2` t2 
    join `project.dataset.table1` t1
    on t1.id = t2.id 
    and t1.starttime < t2.event_time
    and t1.endtime > timestamp_sub(t2.event_time, interval 24 hour) 
    group by t2.id, t2.event, t2.event_time     
    

    如果适用于您问题的样本数据 - 输出是

    【讨论】:

      【解决方案2】:

      如果我理解正确,您可以使用连接来获取所有匹配的行。以下应该得到所有重叠:

      select t2.*, t1.*
      from t2 join
           t1
           on t2.id = t1.id and
              timestamp_add(t2.event_time, interval -1 day) < t1.end_time and
              t2.event_time > t1.start_time;
      

      现在的诀窍是按比例分配金额和总和:

      select t2.event, t2.event_time,
             sum(t1.drug_total_amount *
                 timestamp_diff(second, 
                                least(t2.event_time, t1.end_time),
                                 greatest(timestamp_add(t2.event_time, interval -1 day), t1.start_time)
                               ) /
                 timestamp_diff(second, t1.start_time, t1.end_time)
                ) as drug_amount
      from t2 join
           t1
           on t2.id = t1.id and
              timestamp_add(t2.event_time, interval -1 day) < t1.end_time and
              t2.event_time > t1.start_time
      group by t2.event, t2.event_time;
      

      【讨论】:

      • 谢谢!我认为在你的最后几行中应该是 t1.start_time &lt; t2.event_timet1.end_time &gt; t2.event_time-24
      • @arielhasidim 。 . .我更新了答案中的逻辑。它可能等同于您评论中的内容。但是一天必须在t1 结束之前开始。它必须在t1 中的那个开始之后结束。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-13
      • 2019-01-22
      • 2021-01-03
      • 1970-01-01
      • 2018-10-21
      相关资源
      最近更新 更多