在 postgresql 中查找和汇总具有重叠记录的日期范围

2024-06-19

我有一个大型数据集,我想对记录具有重叠时间的计数进行求和。例如,给定数据

[
  {"id": 1, "name": 'A', "start": '2018-12-10 00:00:00', "end": '2018-12-20 00:00:00', count: 34},
  {"id": 2, "name": 'B', "start": '2018-12-16 00:00:00', "end": '2018-12-27 00:00:00', count: 19},
  {"id": 3, "name": 'C', "start": '2018-12-16 00:00:00', "end": '2018-12-20 00:00:00', count: 56},
  {"id": 4, "name": 'D', "start": '2018-12-25 00:00:00', "end": '2018-12-30 00:00:00', count: 43}
]

您可以看到有 2 个活动重叠的时期。我想根据重叠涉及的活动返回这些“重叠”的总数。所以上面的输出会是这样的:

[
  {start:'2018-12-16', end: '2018-12-20', overlap_ids:[1,2,3], total_count: 109},
  {start:'2018-12-25', end: '2018-12-27', overlap_ids:[2,4], total_count: 62},
]

问题是,如何通过 postgres 查询生成这个?正在研究generate_series,然后计算出每个间隔内有哪些活动,但这不太正确,因为数据是连续的——我确实需要确定确切的重叠时间,然后对重叠活动进行求和。

EDIT Have added another example. As @SRack pointed out, since A,B,C overlap, this means B,C A,B and A,C also overlap. This doesn’t matter since the output I’m looking for is an array of date ranges that contain overlapping activities rather than all the unique combinations of overlaps. Also note the dates are timestamps, so will have millisecond precision and won’t necessarily all be at 00:00:00. If it helps, there would probably be a WHERE condition on the total count. For example only want to see results where total count > 100 enter image description here


(使用具有重叠 A-B 部分的旧数据集)

免责声明:这适用于天间隔,不适用于时间戳。对ts的要求是后来才出现的。

SELECT
    s.acts,
    s.sum,
    MIN(a.start) as start,
    MAX(a.end) as end
FROM (
    SELECT DISTINCT ON (acts)
        array_agg(name) as acts,
        SUM(count)
    FROM
        activities, generate_series(start, "end", interval '1 day') gs
    GROUP BY gs
    HAVING cardinality(array_agg(name)) > 1
) s
JOIN activities a
ON a.name = ANY(s.acts)
GROUP BY s.acts, s.sum
  1. generate_series生成开始和结束之间的所有日期。因此,活动存在的每个日期都会有一行包含特定的count
  2. 对所有日期进行分组,汇总所有现有活动及其计数总和
  3. HAVING过滤掉仅存在一项活动的日期
  4. 因为相同的活动在不同的日子里,我们只需要一个代表:过滤所有重复项DISTINCT ON
  5. 将此结果与原始表连接起来以获得开始和结束。 (注意“end”是Postgres中的保留字,你最好找到另一个列名!)。以前丢失它们会更舒服,但可以在子查询中获取这些数据。
  6. 将此连接分组以获得每个时间间隔的最早和最晚日期。

这是时间戳的版本:

WITH timeslots AS (
    SELECT * FROM (
        SELECT
            tsrange(timepoint, lead(timepoint) OVER (ORDER BY timepoint)),
            lead(timepoint) OVER (ORDER BY timepoint)     -- 2
        FROM (
            SELECT 
                unnest(ARRAY[start, "end"]) as timepoint  -- 1 
            FROM
                activities
            ORDER BY timepoint
        ) s
    )s  WHERE lead IS NOT NULL                            -- 3
)
SELECT 
    GREATEST(MAX(start), lower(tsrange)),                 -- 6
    LEAST(MIN("end"), upper(tsrange)),
    array_agg(name),                                      -- 5
    sum(count)
FROM 
    timeslots t
JOIN activities a
ON t.tsrange && tsrange(a.start, a.end)                   -- 4
GROUP BY tsrange
HAVING cardinality(array_agg(name)) > 1

主要思想是确定可能的时间段。因此,我将每个已知时间(开始和结束)放入排序列表中。因此,我可以获取前两个已知时间(从 A 开始的 17:00 和从 B 开始的 18:00)并检查其中的时间间隔。然后我检查第二个和第三个,然后检查第三个和第四个,依此类推。

第一个时隙中只有 A 适合。在 18-19 的第二个中,B 也很合适。在下一个时段 19-20 中还有 C,从 20 到 20:30 A 不再适合,只有 B 和 C。下一个是 20:30-22,其中只适合 B,最后将 22-23 D 添加到B 和最后但并非最不重要的一点是 D 适合 23-23:30。

因此,我将这个时间列表与时间间隔相交的活动表连接起来。之后,它只是按时间段分组并总结您的计数。

  1. 这会将一行的两个 ts 放入一个数组中,该数组的元素被扩展为每个元素一行unnest。所以我把所有时间都放在一列中,可以简单地排序
  2. 使用铅窗函数 https://www.postgresql.org/docs/current/tutorial-window.html允许将下一行的值放入当前行。所以我可以用这两个值创建一个时间戳范围tsrange
  3. 此过滤器是必要的,因为最后一行没有“下一个值”。这创建了一个NULL值被解释为tsrange作为无穷大。所以这会造成一个令人难以置信的错误时间段。所以我们需要过滤掉这一行。
  4. 将时间段与原始表连接起来。这&&运算符检查两个范围类型是否重叠。
  5. 按单个时间段分组,聚合名称和计数。使用以下方法筛选出仅包含一项活动的时间段HAVING clause
  6. 获得正确的起点和终点有点棘手。因此,起始点要么是活动开始的最大值,要么是时间段的开始(可以使用lower)。例如。以 20-20:30 时段为例:它从 20 点开始,但 B 和 C 都没有在那里开始。结束时间类似。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 postgresql 中查找和汇总具有重叠记录的日期范围 的相关文章

随机推荐

  • 有什么方法可以让dispatch_queue_t在单线程中工作吗?

    这是我的代码 interface MyObject property nonatomic dispatch queue t queue end implementation MyObject NSThread check id init s
  • Jquery Flipbook 上传 PDF

    我正在使用Builtbywill Flipbook div div title This is a page title img src image1 jpg div div img src image2 jpg div div title
  • 将值替换为其各自列的名称

    我有一个数据框 Code 401k CVS 101A true 231N true FD54 true 99JB 85F4 true 我试图用相应的列名称 例如 401k 替换 true 字符值 这是我想要的输出 Code 401k CVS
  • 包管理器控制台中缺少文件错误

    我们的开发团队的一些成员在打开包管理器控制台时开始看到以下错误 它完全阻止我们运行实体框架命令 我们已经检查过并且提到的文件确实存在 GetEvent types ps1xml Diagnostics Format ps1xml Diagn
  • 设置一个带有 JQuery 掩码的文本字段

    使用 watir webdriver 我尝试设置文本字段的值 browser text field id phoneNumbers value input set 5555551234 当我运行该命令时 我可以看到 watir 找到了该字段
  • 可以创建一个独立的方法/函数(没有任何类)

    我正在尝试理解闲聊 是否可以有一个独立的方法 函数 它不属于任何特定类 并且可以稍后调用 amethod amethod called printNl amethod 上面的代码给出以下错误 simpleclass st 1 expecte
  • Typescript 和 React:在组件之间传递 props 与默认 props

    我对 Typescript 和使用 Typescript 创建 React 应用程序相当陌生 我在将道具从一个组件传递到另一个组件时遇到了一些麻烦 我在下面提供了一个示例 我的问题是围绕组件的默认道具 当我在父组件中调用子组件时 出现错误
  • 如何根据特定条件触发电子邮件以在 Jenkins 中成功构建

    每当某个条件在构建后步骤的执行 shell 中成立时成功的构建 我想触发电子邮件发送 问题是 即使条件不成立 构建也会被视为success 我正在尝试实现的内容 if condition true then
  • 单击应用程序的启动图标时会发生什么?

    单击应用程序的启动图标时会发生什么 是否总是发送新意图 或者结果有时与从最近的任务恢复任务相同 如果发送意图 它何时被发送到新活动实例的 onCreate 方法以及何时通过现有活动的 onNewIntent 进行路由 假设意图通过任务中现有
  • c++链接器,如何链接iostream文件?

    我有一个名为main cpp包括iostream 我编译了main cpp它工作没有错误 所以我的问题是 我编译了main cpp我没有链接iostream with main cpp 那么这怎么可能呢 或者编译器是否链接了iostream
  • 如何在 Swift 泛型中说“同一类”

    如果 Swift 泛型类型约束是协议名称 我可以要求受该协议约束的两种类型为同一类型 例如 protocol Flier struct Bird Flier struct Insect Flier func flockTwoTogether
  • Silverlight 4 WCF Ria 服务的轮询模式

    我正在使用 Ria Services 在 Silverlight 中创建一个应用程序 一旦启动服务调用 可能会花费相当多的时间 我一直在寻找增加 WCF 服务超时的方法 但我越想越觉得这不是正确的方法 我宁愿做的是调用 DomainCont
  • 使用 R 的 flextable 包时,有没有办法将传递给 add_header_lines() 的字符串部分加粗

    我正在使用我喜欢的 flextable 包为 Word 文档创建几个表格 但是 我在将表格标题中的部分文本加粗时遇到了一些麻烦 例如 我希望标题为 Table 1 我的表格标题的其余部分 而不是 表 1 我的表格标题的其余部分 I 找到这个
  • 无法访问 res 文件夹?

    我有一个 Java 编程问题 需要帮助 我的类文件位于单独的包中 不是默认包 我正在尝试从我的 res 文件夹访问文件 我已将其添加为类文件夹 使用属性 gt 库 gt 添加类文件夹 在我的类中 我有以下代码 InputStream IS
  • 提供者未返回 ProviderManifest 实例

    当我想配置我的数据源 EntityDataSource 1 并将实体数据模型自动生成的连接字符串分配给它时 我收到错误 无法加载连接字符串中指定的元数据 请考虑重建 Web 项目以构建可能包含元数据的程序集 发生以下错误 提供程序未返回 P
  • Flask-Session 扩展与默认会话

    我在用着 from flask import session app route def main page if session get key print session exist session get key else print
  • 嵌入式签名 api 文档签名

    我正在使用 DocuSign 将电子签名添加到我的请求中 一切正常 现在 我使用嵌入式方法发送签名请求 通过导航到 URL 立即启动我的工作流程 登录后 执行以下代码 我得到 嵌入视图 但是当我粘贴网址尝试在导航中签署文档时 但会将我重定向
  • 如何对需要其他模块的 Node.js 模块进行单元测试以及如何模拟全局 require 函数?

    这是一个简单的例子 说明了我的问题的症结 var innerLib require path to innerLib function underTest return innerLib doComplexStuff module expo
  • 在 Ajax 类型的 Extjs 5 存储上进行本地分页

    我正在开发一个应用程序 从一开始就加载所有数据并不是很不方便 我通过 Ajax 从服务器获取 json 数据 而我的商店执行此操作非常简单 Ext define MODIFE store CentroBeneficio extend Ext
  • 在 postgresql 中查找和汇总具有重叠记录的日期范围

    我有一个大型数据集 我想对记录具有重叠时间的计数进行求和 例如 给定数据 id 1 name A start 2018 12 10 00 00 00 end 2018 12 20 00 00 00 count 34 id 2 name B