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
我必须在 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