从重叠的日期范围中获取不同的连续日期范围

2024-03-27

我需要从重叠日期列表中获取彼此不重叠的日期范围列表,并获取重叠期间的硬币总和。我尝试过用谷歌搜索一个例子,但到目前为止还没有运气。我可能没有使用正确的关键词?

我有一个重叠日期的列表

1.1.2018 - 31.1.2018 80
7.1.2018 - 10.1.2018 10
7.1.2018 - 31.1.2018 10
11.1.2018 - 31.1.2018 5
25.1.2018 - 27.1.2018 5
2.2.2018 - 23.2.2018 100

期望的结果是

1.1.2018 - 6.7.2018 80 coins
7.1.2018 - 10.1.2018 100 coins
11.1.2018 - 24.1.2018 95 coins
25.1.2018 - 27.1.2018 100 coins
28.1.2018 - 31.1.2018 95 coins
2.2.2018 - 23.2.2018 100 coins

这是它应该如何工作的图

|------------------------------|
       |---|
       |-----------------------|
           |-------------------|
                      |---|
                                   |----------------------|
Outcome              
|------|---|----------|---|----|   |----------------------|
   80   100     95     100  95                100

这是我的测试数据

drop table coinsonperiod2;
create table coinsonperiod2(
  id serial,
  startdate date,
  enddate date,
  coins integer,
  userid integer
);
insert into coinsonperiod2 (startdate, enddate, coins,userid) values
  ('2018-01-01','2018-01-31', 80,1)
, ('2018-01-07','2018-01-10', 10,1)
, ('2018-01-07','2018-01-31', 10,1)
, ('2018-01-11','2018-01-31', 5,1)
, ('2018-01-25','2018-01-27', 5,1)
, ('2018-02-02','2018-02-23', 100,2)
, ('2018-01-01','2018-01-31', 80,2)
, ('2018-01-07','2018-01-10', 10,2)
, ('2018-01-07','2018-01-31', 10,2)
, ('2018-01-11','2018-01-31', 5,2)
, ('2018-01-25','2018-01-27', 5,2)
, ('2018-02-02','2018-02-23', 100,3)
; 

更新: 事实上斯蒂芬和乔普的回答并没有达到我想要的结果。两个答案都显示结束日期错误。

当一个周期结束时,下一个周期应在第二天开始(如果有间隙,则稍后开始)。在我期望的结果中,2018年1月1日至2018年1月6日包括第6天。第六名和第七名之间没有差距,因为第七名包含在 7.1.2018-10.1.2018 中。

更新2: 现在我明白了开区间、半开区间和闭区间之间的区别。在乔普解决方案中,必须针对半开区间进行计算,但我期望的结果是闭区间。这就是为什么必须减少结束日期以使结果成为闭区间的原因。如果我错了请纠正我。

我还在示例数据中添加了 userid 并进一步修改了 joops 解决方案。 这是给我想要的结果的查询。

with changes AS (
  SELECT
    userid,
    startdate AS tickdate,
    coins,
    1         AS cover
  FROM coinsonperiod2
  UNION ALL
  -- add 1 day to correct intervals into half open intervals, so the calculation is correct
  SELECT
    userid,
    1 + enddate AS tickdate,
    -1 * coins,
    -1          AS cover
  FROM coinsonperiod2
)
, sumchanges  AS (
    SELECT
      userid,
      tickdate,
      SUM(coins) AS change,
      SUM(cover) AS cover
    FROM changes
    GROUP BY tickdate, userid
)
, aggregated AS (
    SELECT
      userid   AS userid,
      tickdate AS startdate,
      lead(tickdate)
      over www AS enddate,
      sum(change)
      OVER www AS cash,
      sum(cover)
      OVER www AS cover
    FROM sumchanges
    WINDOW www AS (
      partition by userid
      ORDER BY tickdate )
)
-- reduce 1 day from the enddate to make closed interval
SELECT
userid
, startdate
, enddate-1 as enddate
, cash
, cover
FROM aggregated
WHERE cover > 0
ORDER BY userid, startdate
;

Outcome: Outcome


逻辑是:

  • at the 开始间隔的值将其值添加到累积和中
  • at the end一个区间的值从这个总和中减去它的值
  • 但为了sweep日期线,我们必须收集所有(唯一的)日期/时间戳,无论是开始还是停止。

所以重点是:将一系列数据转换为间隔一系列(开始/停止)events,并对这些进行聚合。


-- \i tmp.sql

create table coinsonperiod(
  id serial,
  startdate date,
  enddate date,
  coins integer
);
insert into coinsonperiod (startdate, enddate, coins) values
  ('2018-01-01','2018-01-31', 80)
, ('2018-01-07','2018-01-10', 10)
, ('2018-01-07','2018-01-31', 10)
, ('2018-01-11','2018-01-31', 5)
, ('2018-01-25','2018-01-27', 5)
, ('2018-02-02','2018-02-23', 100)
        ;

WITH changes AS (
    SELECT startdate AS tickdate , coins
            , 1 AS cover
    FROM coinsonperiod
    UNION ALL
    -- add 1 day to convert to half-open intervals
    SELECT 1+enddate AS tickdate, -1* coins
            , -1 AS cover
    FROM coinsonperiod
    )
, sumchanges  AS (
        SELECT tickdate, SUM(coins) AS change, SUM(cover) AS cover
        FROM changes
        GROUP BY tickdate
        )
, aggregated AS (
        SELECT
        tickdate AS startdate
        , lead(tickdate) over www AS enddate
        , sum(change) OVER www AS cash
          -- number of covered intervals
        , sum(cover) OVER www AS cover
        FROM sumchanges
        WINDOW www AS (ORDER BY tickdate)
        )
             -- substract one day from enddate to correct back to closed intervals
SELECT startdate, enddate-1 AS enddate, cash, cover
FROM aggregated
WHERE cover > 0
ORDER BY startdate
        ;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从重叠的日期范围中获取不同的连续日期范围 的相关文章

随机推荐

  • Android Studio 2.2 预览版在实现数据绑定时抛出错误

    我已将 android studio 更新到 2 2 预览版 1 并按指定应用了 google 和 firebase 的指定依赖项 但仍然出现以下错误 EmptyThrowable Wrong dependency type class c
  • XMLHttpRequest setRequestHeader() --> 有没有办法设置标头值,而不是附加到它?

    from http www w3 org TR XMLHttpRequest the setrequestheader method http www w3 org TR XMLHttpRequest the setrequestheade
  • 验证正整数

    我只想允许数字字段使用正整数 包括零 如何使用 JSR 303 定义此验证 I tried Min value 0 message msg1 但它允许浮点值 如 1 2 Digits fraction 0 integer 10 messag
  • 线程拥有堆栈和进程拥有堆栈的策略是什么?

    线程拥有堆栈和进程拥有堆栈的策略是什么 如果我们有 10 个进程 那么我们有多少个堆栈 10 个 如果一个进程下有 10 个线程 那么我们有多少个堆栈 1 所有线程共享同一个堆栈 Thanks 如果你考虑一下堆栈是什么 那么共享堆栈是没有意
  • Wordapp 未在线程或并行进程中关闭

    下面的代码通常可以工作 并且在将 docx doc 保存到 pdf 后打开和关闭 word 但是当在线程或并行 for 循环中使用以下代码时 它不会 有任何想法吗 我已经提供了下面的所有代码 这是在函数中使用时工作正常的代码 wordApp
  • 如何正确对整数数组进行排序

    尝试从我知道仅包含整数的数组中获取最高和最低值似乎比我想象的更难 var numArray 140000 104 99 numArray numArray sort console log numArray 我希望这能显示99 104 14
  • Eclipse 在 pom.xml 文件中显示错误:cvc-datatype-valid.1.2.1: '${MYVAR}' 不是 'boolean' 的有效值

    我有一个 Maven 项目 可以在命令行上正常构建 我想在 Eclipse Luna 4 4 1 中编辑项目文件 但是当我加载项目时 它在我的 pom xml 文件中报告以下错误 cvc datatype valid 1 2 1 MYVAR
  • 根据值将逗号分隔的数字列拆分为多列

    我有一个专栏f在我的数据框中 我想根据该列中的值扩展到多个列 例如 df lt structure list f c NA 18 17 10 12 8 17 11 6 18 12 12 NA 17 11 12 Names f row nam
  • 使用特定的 url 地址从 java 代码关闭浏览器

    1 我想使用我的java代码中的url地址关闭特定的浏览器选项卡 因为它是一个客户端服务器应用程序 我想使用客户端应用程序中的 url 地址关闭浏览器选项卡 服务器端将有一个 jar 它将与客户端请求进行通信 并从客户端获取 url 并根据
  • JSON.NET序列化没有属性名称的字典[重复]

    这个问题在这里已经有答案了 大家 我有字典属性名称的 json 序列化问题 这是我的代码 public class MyClass public string A get set public string B get set public
  • 用于调试的 YII 日志记录

    在很多情况下 Xdebug不适合调试 因为它涉及点击运行到特定的代码行 我想使用类似的东西cakePHP调试功能 供开发人员将类的特定属性的值输出到浏览器 我在用Yii framework这是我的配置yii log in the main
  • 如何实例化对象的静态向量?

    我有一个 A 类 它有一个静态对象向量 对象属于 B 类 class A public static void InstantiateVector private static vector b vector of B 在函数 Instan
  • 修改现有的 Android ROM 以控制用户操作

    我正在为客户创建一个 Android 应用程序 该应用程序将预安装并与手机一起分发 现在客户要求我锁定 ROM 以防止未来的用户使用除此应用程序之外的任何其他应用程序 IE 没有浏览 没有电子邮件 没有任何可能产生任何费用的东西等 现在 经
  • 在 CMD 批处理脚本中调用标签时如何利用超过 9 个参数?

    我想知道如何在调用标签时在批处理脚本中调用超过 9 个参数 例如 下面显示我分配了 12 个参数 并尝试回显所有这些参数 CALL LABEL one two three four five six seven eight nine ten
  • Kafka消费者默认组ID

    我正在使用 Apache Kafka 及其 Java 客户端 我发现消息在属于同一组的不同 Kafka Consumer 之间进行负载平衡 即共享相同的组 id 在我的应用程序中 我需要所有消费者阅读所有消息 所以我有几个问题 如果我没有在
  • 在 IntelliJ IDEA 中编写并运行 pyspark

    我正在尝试在 IntelliJ 中使用 Pyspark 但我不知道如何正确安装它 设置项目 我可以在 IntelliJ 中使用 Python 并且可以使用 pyspark shell 但我无法告诉 IntelliJ 如何查找 Spark 文
  • 如何在Python中导入其他项目的函数?

    我在一个项目中有一些代码 我想在另一个项目中重用它们 我需要做什么 在两个文件夹中 才能执行此操作 目录结构类似于 Foo Project1 file1 py file2 py Bar Project2 fileX py fileY py
  • 在单个查询中获取分页行和总计数

    核心要求 查找 a 的最新条目person id by submission date对于指定的过滤条件type plan status 可能有更多这样的过滤器 但无论如何 按提交日期返回最新的逻辑是相同的 有两个主要用途 一是在 UI 中
  • Android setContentView 还是 Intents?

    我有一个非常简单的 2 屏幕 Android 应用程序 简单地通过 setContentView 切换布局有什么缺点吗 或者我应该使用意图吗 如果出现问题 我不想打扰我的应用程序 另一件需要考虑的事情是 活动形成了stack http de
  • 从重叠的日期范围中获取不同的连续日期范围

    我需要从重叠日期列表中获取彼此不重叠的日期范围列表 并获取重叠期间的硬币总和 我尝试过用谷歌搜索一个例子 但到目前为止还没有运气 我可能没有使用正确的关键词 我有一个重叠日期的列表 1 1 2018 31 1 2018 80 7 1 201