sql,大查询:聚合变量中两个字符串之间的所有条目

sql, big query: aggregate all entries between two strings in a variable

我必须在 bigQuery 中解决这个问题。我的 table:

中有此专栏
event            | time
_________________|____________________
start            | 1
end              | 2
random_event_X   | 3
start            | 4 
error_X          | 5 
error_Y          | 6
end              | 7
start            | 8
error_F          | 9
start            | 10
random_event_Y   | 11
error_z          | 12
end              | 13

我想,从end事件记录一切,直到start出现,然后再数数。一切都可能发生在开始和结束之间以及它之外。有结束就有开始但有开始未必有结束

期望输出如下:

string_agg                            | count
"start, end"                          |  1
"start, error_X, error_Y, end"        |  1
"start, random_event_Y error_Z, end"  |  1

如果 start 有一个 end,则每个开始和结束之间的所有内容。所以没有时间 3 的 random_event_X,时间 8 的 start 或时间 9 的 error_F

我找不到解决方案并且很难理解如何解决这个问题。欢迎任何帮助或建议。

SQL 表表示 无序 集——这在大规模并行的列式数据库中尤其如此,例如 BigQuery。

因此,我必须假设您还有一些其他列指定了排序。如果是这样,您可以使用累积和来识别组然后聚合:

select grp,
       string_agg(event, ',' order by time)
from (select t.*,
             countif(event = 'start') over (order by time) as grp
      from t
     ) t
group by grp
order by min(time);

注意:我还建议您使用 array_agg() 而不是 string_agg()。数组通常比字符串更容易使用。

编辑:

我明白了,您最多只想要 end。在这种情况下,另一层 window 函数:

select grp,
       string_agg(event, ',' order by <ordering col>)
from (select t.*,
             max(case when event = 'end' then time end) over (partition by grp) as max_end_time
      from (select t.*,
                   countif(event = 'start') over (order by <ordering col>) as grp
            from t
           ) t
     ) t
where max_end_time is null or time <= max_end_time
group by grp
order by min(<ordering col>);

以下适用于 BigQuery 标准 SQL

#standardSQL
SELECT agg_events, COUNT(1) cnt 
FROM (
  SELECT STRING_AGG(event ORDER BY time) agg_events, COUNTIF(event IN ('start', 'end')) flag   
  FROM (
    SELECT *, COUNTIF(event = 'start') OVER(PARTITION BY grp1 ORDER BY time) grp2     
    FROM (
      SELECT *, COUNTIF(event = 'end') OVER(ORDER BY time DESC) grp1 
      FROM `project.dataset.table`
    )
  )
  GROUP BY grp1, grp2
)
WHERE flag = 2
GROUP BY agg_events   

如果应用于您问题中的示例数据 - 结果是

Row agg_events                          cnt  
1   start,random_event_Y,error_z,end    1    
2   start,error_X,error_Y,end           1    
3   start,end                           1