Redshift:在列表中查找 MAX,忽略非增量数字

Redshift: Find MAX in list disregarding non-incremental numbers

我在一家体育电影分析公司工作。我们有具有唯一团队 ID 的团队,我想找到从今天开始他们将电影上传到我们网站的连续周数。每个上传在单独的 table 中也有自己的行,我可以加入 teamid 并且有一个唯一的上传日期。到目前为止,我整理了一个简单的查询,该查询提取每个唯一的 DATEDIFF(week) 值和 teamid 上的组。

Select teamid, MAX(weekdiff)
(Select teamid, DATEDIFF(week, dateuploaded, GETDATE()) as weekdiff 
from leroy_events
group by teamid, weekdiff)

我得到的是一个 teamID 列表和独特的每周日期差异。然后我想在不破坏 1 增量的情况下找到每个 teamID 的最大值。例如,如果我的数据集是:

Team     datediff
11453    0
11453    1
11453    2
11453    5
11453    7
11453    13

我希望团队的最大值:11453 为 2。

任何想法都会很棒。

我已经简化了你的例子,假设我已经有一个 table 和 weekdiff 列。这就是你用 DATEDIFF 计算它的方法。

首先,我使用 LAG() window 函数将 weekdiff 的先前值(在有序集中)分配给当前行。

然后,使用 WHERE 条件,我正在检索 max(weekdiff) 值,该值具有连续 weekdiff 的先前值 current_value - 1

数据:

create table leroy_events ( teamid int, weekdiff int);
insert into leroy_events values (11453,0),(11453,1),(11453,2),(11453,5),(11453,7),(11453,13);

代码:

WITH initial_data AS (
Select 
    teamid, 
    weekdiff,
    lag(weekdiff,1) over (partition by teamid order by weekdiff) as lag_weekdiff
from
    leroy_events
)
SELECT
  teamid,
  max(weekdiff) AS max_weekdiff_consecutive
FROM
  initial_data
WHERE weekdiff = lag_weekdiff + 1 -- this insures retrieving max() without breaking your consecutive increment
GROUP BY 1

SQLFiddle 与您的示例数据一起查看此代码的工作原理。

结果:

teamid  max_weekdiff_consecutive
11453   2

您可以使用 SQL window 函数来探测 table 的行之间的关系。在这种情况下,lag() 函数可用于查看相对于给定顺序和分组的前一行。这样您就可以确定给定的行是否属于一组连续的行。

您仍然需要整体聚合或过滤以将每个感兴趣的组(即每个团队)的行数减少到 1。在这种情况下聚合很方便。总的来说,它可能看起来像这样:

select
  team,
  case min(datediff)
    when 0 then max(datediff)
    else -1
  end as max_weeks
from (
    select
      team,
      datediff,
      case
        when (lag(datediff) over (partition by team order by datediff) != datediff - 1)
          then 0
        else 1
      end as is_consec
    from diffs
  ) cd
where is_consec = 1
group by team

内联视图只是向数据添加一个 is_consec 列,标记每一行是否是一组连续行的一部分。外部查询对该列进行过滤(您不能直接对 window 函数进行过滤),并从每个团队的剩余行中选择最大值 datediff

这里有一些细微之处:

  • 内联视图中的 case 表达式是按原样编写的,以利用这样一个事实,即为每个分区的第一行计算的 lag() 将是 NULL,它不会评估不等于(或等于)任何值。因此,每个分区中的第一行始终标记为连续。

  • 外部 select 子句中的 case testing min(datediff) 选取没有 datediff = 0 记录的团队,并分配 -1 到第 max_weeks 列。

  • 如果他们组中的第一个没有datediff = 0,也可以将行标记为不连续,但这样你就会从结果中完全失去这些团队。