google-bigquery - SQL UDF - 结构差异
问题描述
我们有一个表,其中包含 2 个“结构”类型的顶级列 - 一个是“之前”,一个是“之后”图像。结构模式是非平凡的 - 嵌套,数组的深度可变。是从复制发送给我们的,所以模式总是相同的(但模式当然可以在某个时候更新,但总是在一起)
目标是两个输入结构,返回之前和之后的 2 个结构“差异”,仅包含已更改的字段 - 本质上是复制源产生的更改的“增量”差异。我们知道有些东西发生了变化,但不是“什么”,因为我们得到了完整的前后图像。此原始数据位于 BQ 中,然后从那里进行处理,但需要确定更精细的更改以进行高阶 BQ 处理。
表模式非常宽(1000 个叶子字段),并且填充的数据相当空闲(因此快照的两侧都会出现很多空值) - 因此在执行超过 10 秒时需要尽可能地保持最佳性能数百万行。
所有东西都可以为空,以获得最大的灵活性。
所以变化可能看起来像:
- 空 -> 值
- 值 -> 空
- 值A -> 值B
数组:
递归使用上面的结构数组,如果这样更容易,可以放宽排序吗?
这可能是不可能的。
我还没有尝试过这个,因为它看起来真的很困难,所以我希望社区研究人员对此提供一些支持。我觉得阵列可能是困难的部分。在 Python 中可能有一种简单的方法,我什至没有使用 JOSN 工具进行一些 JSON 转换和比较?感觉这也是 BQ 内置的一个超级酷的功能,所以如果可以让它工作,将为它添加一个功能请求。
我想有一个 SQL UDF 以供重用(我们有 SQL 技能而不是 python,尽管如果在 python 中更容易那就没问题了),现在有了持久 SQL UDF 的新特性,这似乎是询问和测试该特性的正确时机!
sql def struct_diff(结构前,结构后)
(beforeChange, afterChange) - 签名类型,但愿意接受建议?
解决方案
似乎很难得到一段可重用的代码。由于目前不支持 SQL UDF 的递归函数,因此您不能对嵌套结构使用递归方法。
虽然,您可能能够获得一些特定的 SQL UDF 函数,具体取决于您的数组和结构结构。您可以使用这样的方法来比较结构。
CREATE TEMP FUNCTION final_compare(s1 ANY TYPE, s2 ANY TYPE) AS (
STRUCT(s1 as prev, s2 as cur)
);
CREATE TEMP FUNCTION compare(s1 ANY TYPE, s2 ANY TYPE) AS (
STRUCT(final_compare(s1.structA, s2.structA))
);
您可以使用UNNEST
arrays ,最终的 SQL UDF 将真正取决于您的数据。
正如@rtenha 所建议的那样,Python 可能更容易处理这个问题。
最后,我使用 JavaScript UDF 做了一些测试,结果基本相同,如果不是比 SQL UDF 最差的话。
控制台允许函数的递归定义,但是它会在执行期间失败。此外,javascript不允许ANY TYPE
签名上的数据类型,因此您必须定义整个 STRUCT 定义或使用解决方法,例如应用于TO_JSON_STRING
您的结构,以便将其作为字符串传递。
推荐阅读
- node.js - 强制 API 超时时节点 JS 中的套接字挂断错误
- android - 无法在 Android 模拟器上从本地 Flask 服务器接收 200 ok 响应
- java - 我在使用命令提示符执行 java 程序时遇到问题
- javascript - 当我在 JS worker 中导入 WASM 时,“无法解析模块说明符”或“未定义窗口”
- database - 我的应用程序 (MongoDB) 需要哪个 M.. 层?
- security - POST 请求 - 检测到 406 安全事件
- python - scipy.optimize 与 SLSQP。某些约束的“LSQ 子问题中的奇异矩阵 E”
- python - 如何将值拆分为列中的 int 和 string 并计算持续时间
- c++ - 移动在 C++ 控制台游戏中不起作用(使用 _kbhit 和 _getch)
- kubernetes - 防止 VirtualService 路由到空/不健康的目的地?