代码之家  ›  专栏  ›  技术社区  ›  shadowtalker

在基于时间的关联中,如何在任何给定时间获得有效的关联?

  •  0
  • shadowtalker  · 技术社区  · 3 年前

    假设我有一个从用户到组的“分配”表,其中每个用户在任何给定时间最多可以分配到一个组:

    create table players_teams_assignments (
      user_id          integer not null,
      assignment_time  timestamp not null,
      group_id         integer,
      primary key (
        user_id, assignment_time
      )
    )
    

    在某个任意的时间 t ,如何获取当前分配给某个任意组的所有用户ID g ?

    可能有 在时间分配的用户

    1 回复  |  直到 3 年前
        1
  •  0
  •   shadowtalker    3 年前

    一个解决方案涉及构建 间隔 指定处于活动状态的时间,然后筛选覆盖所需时间的间隔 t

    例如,我们可以使用window函数轻松地做到这一点 lead() :

    with assignment_intervals as (
      select
        user_id,
        assignment_time as assignment_start,
        lead(assignment_time) over (
          partition by user_id
          order by assignment_time
        ) as assignment_end,
        group_id
      from players_teams_assignments
    )
    select group_id
    where
      assignment_start <= t and
      coalesce(assignment_end > t, true)
    

    我相信 引线() 一些SQL标准的一部分(尽管我不知道是哪一个)。如果您的数据库不支持以下内容 引线() ,您将需要以其他方式构造这些区间。

    注意使用 coalesce 在这里在雪花中 引线() 退货 NULL 在窗口的最后一行。将比较与 true 相当于将赋值的结束视为在未来无限期地结束,表示数据中最后一个已知的赋值。

    还要注意的是,在这种情况下,我使用了左侧闭合、右侧打开的区间。也就是说,每个间隔从当前分配开始,在下一个分配之前结束。对于大多数用例来说,这是有意义的默认值,从而导致连续、不相交的间隔覆盖。