通过正则表达式过滤器过滤 Google BigQuery 列
Posted
技术标签:
【中文标题】通过正则表达式过滤器过滤 Google BigQuery 列【英文标题】:Filter Google BigQuery columns by regex filter 【发布时间】:2020-01-16 14:08:32 【问题描述】:目前,我正在努力在 Google Big Query 中创建快速优化的查询。
假设,有一个表,有 10k 行和 4k 列:
| TP_001_A | TP_001_B | TP_002_A | TP_002 | ... | TP_099_B |
----+----------+----------+----------+----------+----------+----------+
1 | 0.33 | 0.33 | 0.33 | 0.33 | 0.33 | 0.37 |
2 | 0.33 | 0.33 | 0.31 | 0.33 | 0.33 | 0.33 |
3 | 0.33 | 0.33 | 0.33 | 0.33 | 0.33 | 0.33 |
4 | 0.35 | 0.33 | 0.33 | 0.33 | 0.34 | 0.33 |
...
9999| 0.33 | 0.33 | 0.33 | 0.33 | 0.33 | 0.33 |
我的任务是根据正则表达式过滤器选择列(例如,只有名称以 TP_001 开头的列),从而生成这样的表:
| TP_001_A | TP_001_B |
----+----------+----------+
1 | 0.33 | 0.33 |
2 | 0.33 | 0.33 |
3 | 0.33 | 0.33 |
4 | 0.35 | 0.33 |
...
9999| 0.33 | 0.33 |
到目前为止,我已经解决了这个问题并查询了整个表,然后使用 pandas 库对其进行过滤,这很慢,因为在大表中下载时间和整体 pandas 很慢。
在网上搜索后,我发现列名可以通过如下查询来检索:
SELECT column_name
FROM my_view.INFORMATION_SCHEMA.COLUMNS
WHERE table_name="my_table"
我可以在哪里使用 REGEXP_EXTRACT_ALL 函数,并过滤正确的列名,但它给了我很难在主查询中使用的单独表。
但是这个解决方案有一个问题:尽管速度非常快,但正在处理大量数据(指示显示 10MB,但看起来很多)。
是否有任何适当的方式来进行此类查询或其他方式来优化仅检索过滤的列?
【问题讨论】:
如果您已经在使用 python,请查询 Information_SCHEMA,遍历结果并过滤以获取所需的列名,然后从这些结果中构建新的 select 语句,然后针对新字符串执行查询。 【参考方案1】:是否有任何适当的方法来进行这样的查询(通过正则表达式过滤器过滤 Google BigQuery 列)...
无法使用纯 BigQuery SQL 执行此类查询 - 如果您愿意,可以submit feature request。
同时,您可以使用您选择的任何BigQuery Client Library 以编程方式构建所需的选择语句并执行它 - 超级简单且可行的选项
... 或其他优化仅检索过滤列的方法?
如果由于某种原因您必须使用纯 BQ SQL - 我看到的唯一选择是扁平化,如下例所示(您的问题中的虚拟数据略有修改)
#standardSQL
WITH `project.dataset.table` AS (
SELECT 1 id, 0.3301 TP_001_A, 0.3305 TP_001_B, 0.3309 TP_002_A, 0.3313 TP_002, 0.3317 TP_003, 0.3721 TP_099_B UNION ALL
SELECT 2, 0.3302, 0.3306, 0.3110, 0.3314, 0.3318, 0.3322 UNION ALL
SELECT 3, 0.3303, 0.3307, 0.3311, 0.3315, 0.3319, 0.3323 UNION ALL
SELECT 4, 0.3504, 0.3308, 0.3312, 0.3316, 0.3420, 0.3324
)
SELECT id, TRIM(kv.key, '"') col, kv.value
FROM `project.dataset.table` t,
UNNEST(ARRAY(
SELECT AS STRUCT SPLIT(kv, ':')[OFFSET(0)] key, SPLIT(kv, ':')[OFFSET(1)] value
FROM UNNEST(SPLIT(TRIM(TO_JSON_STRING(t), ''))) kv
WHERE STARTS_WITH(SPLIT(kv, ':')[OFFSET(0)], '"TP_001')
)) kv
-- ORDER BY id
结果
Row id col value
1 1 TP_001_A 0.3301
2 1 TP_001_B 0.3305
3 2 TP_001_A 0.3302
4 2 TP_001_B 0.3306
5 3 TP_001_A 0.3303
6 3 TP_001_B 0.3307
7 4 TP_001_A 0.3504
8 4 TP_001_B 0.3308
根据我的经验 - 对于大多数涉及动态列列表的实际用例,上述输出比在列中显示更有用
显然,如果您有更复杂的过滤器,您可以将STARTS_WITH(..., '"TP_001')
替换为 REGEXP_CONTAINS
【讨论】:
以上是关于通过正则表达式过滤器过滤 Google BigQuery 列的主要内容,如果未能解决你的问题,请参考以下文章
如何通过 Pyspark 中同一数据框中另一列的正则表达式值过滤数据框中的一列