在 bigQuery 中迭代 table 行
Iterate table rows in bigQuery
我正在评估 bigQuery。我有一个 table 可以捕捉员工的动作。
Table (location_history):
emp String
lat String
lng String
district String
timestamp timestamp
样本:
emp | lat | lng | district| timestamp
------------------------------------------------
emp1 | 100.234 | 99.456 | ABC | 2021-02-09 03:00:00
emp1 | 100.234 | 99.456 | XYZ | 2021-02-09 04:00:00
emp1 | 100.234 | 99.456 | ABC | 2021-02-09 05:00:00
emp1 | 100.234 | 99.456 | XYZ | 2021-02-09 06:00:00
emp1 | 100.234 | 99.456 | XYZ | 2021-02-09 07:00:00
emp1 | 100.234 | 99.456 | ABC | 2021-02-09 08:00:00
emp1 | 100.234 | 99.456 | WWW | 2021-02-09 09:00:00
注意:这是每个员工在区域内的流动。除了时间戳,员工可以从一个地区移动到另一个地区。此外,当我们捕获每个 lng,lat(地区是一个多边形,superArea)时,即使对于一个地区也可能有数百个重复(相同)行。
我需要的是跟踪访问每个地区的每位员工的历史记录。这样我就可以知道哪位员工整天在哪个区。这可以是整个月的轨道。我们在上面 table 得到的行(每天)超过 1000 亿。
两个问题:
- 在任何存储过程(无论任何数据库)中处理大量行是个好主意吗?与语言相比,SP 的性能因素是什么(服务器端 java,如果忽略获取和插入而只关注迭代或操作 rows/resultSet)
- BigQuery 是否允许对行进行迭代(来自 table 使用 select 语句)?否则解决方案是什么?
提前致谢。
更新:
预期结果是计算员工在每个地区花费的时间。流程将执行:
- 查询以使用 (select * 来自 location_history order by emp,district)
- 然后遍历每一行,每一行都依赖于前一行来计算在特定区域花费的时间
更新二:
这应该分别计算每个员工的持续时间(将他们分组),而不是根据其他员工 activity 计算。因此,每个员工的每个第一个 activity 将有 null/zero 持续时间,如果找到下一个 activity 将从上一行开始计算。希望这是有道理的。
您无法比较所有数据库引擎的存储过程。每一个都有自己的特点。反正对于big query来说,处理大量的数据不是问题,只要你有钱买这个!
关于语言的处理,见仁见智。对我来说,如果你是一名核心开发人员并且掌握了所有优化技巧,那么你可以构建与内置数据库一样高效的东西。数据库引擎经过优化,可以有效地处理数据集,对它们进行排序,对它们进行索引(...)。此外,留在数据库中,您不会浪费网络时间将数据导出到另一个系统来执行处理。
正如 Google 所说,“如果您可以在 SQL 中描述您的操作数据,BigQuery 将始终比其他方法更快、更便宜,例如 Dataflow 或 Dataproc”。但是,BigQuery 无法执行外部 API 调用。如果这是您的用例,您需要在 BigQuery
之外处理数据
关于第二点,BigQuery 提出 Analytics function,我认为您正在寻找这个。如果您需要帮助来构建请求,您能否提供预期结果的示例?
编辑 1
如果您尝试此查询(使用您的示例数据进行测试)
with data as (
select "emp1" as emp, 100.234 as log, 99.456 as lat, "ABC" as district, ("2021-02-09 03:00:00") as date
UNION ALL
select "emp1" as emp, 100.234 as log, 99.456 as lat, "XYZ" as district, ("2021-02-09 04:00:00") as date
UNION ALL
select "emp1" as emp, 100.234 as log, 99.456 as lat, "ABC" as district, ("2021-02-09 05:00:00") as date
UNION ALL
select "emp1" as emp, 100.234 as log, 99.456 as lat, "XYZ" as district, ("2021-02-09 06:00:00") as date
UNION ALL
select "emp1" as emp, 100.234 as log, 99.456 as lat, "XYZ" as district, ("2021-02-09 07:00:00") as date
UNION ALL
select "emp1" as emp, 100.234 as log, 99.456 as lat, "ABC" as district, ("2021-02-09 08:00:00") as date
UNION ALL
select "emp1" as emp, 100.234 as log, 99.456 as lat, "WWW" as district, ("2021-02-09 09:00:00") as date
)
select emp, date, district as current_distinct, LAG(district) over (ORDER by date) as prev_district from data
你可以得到这样的结果:
emp date current_distinct prev_district
emp1 2021-02-09 03:00:00 ABC
emp1 2021-02-09 04:00:00 XYZ ABC
emp1 2021-02-09 05:00:00 ABC XYZ
emp1 2021-02-09 06:00:00 XYZ ABC
emp1 2021-02-09 07:00:00 XYZ XYZ
emp1 2021-02-09 08:00:00 ABC XYZ
emp1 2021-02-09 09:00:00 WWW ABC
以下适用于 BigQuery 标准 SQL
select emp, district, date,
datetime_diff(
date,
lag(date) over(partition by emp order by date),
minute
) minutes_in_district
from `project.dataset.table`
如果应用于您问题中的示例数据 - 输出为
我假定您的日期列是 DATETIME 数据类型
如果它是 TIMESTAMP 数据类型 - 您应该使用 timestamp_diff 函数而不是 datetime_diff
我正在评估 bigQuery。我有一个 table 可以捕捉员工的动作。
Table (location_history):
emp String
lat String
lng String
district String
timestamp timestamp
样本:
emp | lat | lng | district| timestamp
------------------------------------------------
emp1 | 100.234 | 99.456 | ABC | 2021-02-09 03:00:00
emp1 | 100.234 | 99.456 | XYZ | 2021-02-09 04:00:00
emp1 | 100.234 | 99.456 | ABC | 2021-02-09 05:00:00
emp1 | 100.234 | 99.456 | XYZ | 2021-02-09 06:00:00
emp1 | 100.234 | 99.456 | XYZ | 2021-02-09 07:00:00
emp1 | 100.234 | 99.456 | ABC | 2021-02-09 08:00:00
emp1 | 100.234 | 99.456 | WWW | 2021-02-09 09:00:00
注意:这是每个员工在区域内的流动。除了时间戳,员工可以从一个地区移动到另一个地区。此外,当我们捕获每个 lng,lat(地区是一个多边形,superArea)时,即使对于一个地区也可能有数百个重复(相同)行。
我需要的是跟踪访问每个地区的每位员工的历史记录。这样我就可以知道哪位员工整天在哪个区。这可以是整个月的轨道。我们在上面 table 得到的行(每天)超过 1000 亿。
两个问题:
- 在任何存储过程(无论任何数据库)中处理大量行是个好主意吗?与语言相比,SP 的性能因素是什么(服务器端 java,如果忽略获取和插入而只关注迭代或操作 rows/resultSet)
- BigQuery 是否允许对行进行迭代(来自 table 使用 select 语句)?否则解决方案是什么?
提前致谢。
更新: 预期结果是计算员工在每个地区花费的时间。流程将执行:
- 查询以使用 (select * 来自 location_history order by emp,district)
- 然后遍历每一行,每一行都依赖于前一行来计算在特定区域花费的时间
更新二: 这应该分别计算每个员工的持续时间(将他们分组),而不是根据其他员工 activity 计算。因此,每个员工的每个第一个 activity 将有 null/zero 持续时间,如果找到下一个 activity 将从上一行开始计算。希望这是有道理的。
您无法比较所有数据库引擎的存储过程。每一个都有自己的特点。反正对于big query来说,处理大量的数据不是问题,只要你有钱买这个!
关于语言的处理,见仁见智。对我来说,如果你是一名核心开发人员并且掌握了所有优化技巧,那么你可以构建与内置数据库一样高效的东西。数据库引擎经过优化,可以有效地处理数据集,对它们进行排序,对它们进行索引(...)。此外,留在数据库中,您不会浪费网络时间将数据导出到另一个系统来执行处理。
正如 Google 所说,“如果您可以在 SQL 中描述您的操作数据,BigQuery 将始终比其他方法更快、更便宜,例如 Dataflow 或 Dataproc”。但是,BigQuery 无法执行外部 API 调用。如果这是您的用例,您需要在 BigQuery
之外处理数据关于第二点,BigQuery 提出 Analytics function,我认为您正在寻找这个。如果您需要帮助来构建请求,您能否提供预期结果的示例?
编辑 1
如果您尝试此查询(使用您的示例数据进行测试)
with data as (
select "emp1" as emp, 100.234 as log, 99.456 as lat, "ABC" as district, ("2021-02-09 03:00:00") as date
UNION ALL
select "emp1" as emp, 100.234 as log, 99.456 as lat, "XYZ" as district, ("2021-02-09 04:00:00") as date
UNION ALL
select "emp1" as emp, 100.234 as log, 99.456 as lat, "ABC" as district, ("2021-02-09 05:00:00") as date
UNION ALL
select "emp1" as emp, 100.234 as log, 99.456 as lat, "XYZ" as district, ("2021-02-09 06:00:00") as date
UNION ALL
select "emp1" as emp, 100.234 as log, 99.456 as lat, "XYZ" as district, ("2021-02-09 07:00:00") as date
UNION ALL
select "emp1" as emp, 100.234 as log, 99.456 as lat, "ABC" as district, ("2021-02-09 08:00:00") as date
UNION ALL
select "emp1" as emp, 100.234 as log, 99.456 as lat, "WWW" as district, ("2021-02-09 09:00:00") as date
)
select emp, date, district as current_distinct, LAG(district) over (ORDER by date) as prev_district from data
你可以得到这样的结果:
emp date current_distinct prev_district
emp1 2021-02-09 03:00:00 ABC
emp1 2021-02-09 04:00:00 XYZ ABC
emp1 2021-02-09 05:00:00 ABC XYZ
emp1 2021-02-09 06:00:00 XYZ ABC
emp1 2021-02-09 07:00:00 XYZ XYZ
emp1 2021-02-09 08:00:00 ABC XYZ
emp1 2021-02-09 09:00:00 WWW ABC
以下适用于 BigQuery 标准 SQL
select emp, district, date,
datetime_diff(
date,
lag(date) over(partition by emp order by date),
minute
) minutes_in_district
from `project.dataset.table`
如果应用于您问题中的示例数据 - 输出为
我假定您的日期列是 DATETIME 数据类型 如果它是 TIMESTAMP 数据类型 - 您应该使用 timestamp_diff 函数而不是 datetime_diff