从 R 转换为 BigQuery(或您使用的任何数据库语言)时可以创建的查询类型dbplyr
取决于 R 和 BigQuery 之间定义的转换。我找不到任何建议UNNEST
在现有dbplyr
包中定义翻译的示例。参考1、参考2
一种解决方法是定义一个自定义函数,而不是在 内进行翻译dbplyr
,而是在dbplyr
. 在我需要PIVOT
SQL 但找不到tidyr::spread
.
该方法有效,因为远程表dbplyr
由两件事定义:(1)到远程数据库的连接,(2)返回表的当前视图的代码/查询。因此,一旦dbplyr
将 R 转换为 BigQuery 或 SQL,它就会更新定义的后半部分。
我们可以使用自定义函数来做到这一点:
unnest <- function(input_tbl, select_columns, array_column, unnested_columns){
# extract connection
db_connection <- input_tbl$src$con
select_columns = paste0(select_columns, collapse = ", ")
unnested_columns = paste0(paste0("un.", unnested_columns), collapse = ", ")
# build SQL unnest query
sql_query <- dbplyr::build_sql(
con = db_connection
,"SELECT ", select_columns, ", ", position, ", ", unnested_columns, "\n"
,"FROM (\n"
,dbplyr::sql_render(input_tbl)
,"\n) AS src\n"
,"CROSS JOIN UNNEST(", array_column, ") AS un WITH OFFSET position"
)
return(dplyr::tbl(db_connection, dbplyr::sql(sql_query)))
}
请注意,我是dbplyr
用户,但不是 BigQuery 用户,所以我在上面的语法可能不是很完美。我已经关注了这个问题和这个问题的语法。
示例使用:
remote_table = tbl(bigquery_connection, from = "table_name")
unnested_table = unnest(remote_table, "ID", "array_col", "list")
# check syntax of dbplyr query
unnested_table %>% show_query()
# if this is not a valid bigquery query then next command will error
# view top 10 rows
unnested_table %>% head(10)
如果remote_table
看起来像:
ID ARRAY_COL
01 list = [a,b,c]
02 list = [d,e]
03 list = [q]
然后unnested_table
应该看起来像:
ID POSITION un.list
01 0 a
01 1 b
01 2 c
02 0 d
02 1 e
03 0 q
unnested_table %>% show_query()
应该看起来像:
<SQL>
SELECT *, position, un.list
FROM (
SELECT *
FROM table_name
) AS src
CROSS JOIN UNNEST(ARRAY_COL) AS un WITH OFFSET position
更新以匹配目标查询
我知道没有可以轻松dbplyr
翻译的功能,_TABLE_SUFFIX BETWEEN "20191101" AND "20191102"
因此您将不得不以另一种方式处理这个问题——也许循环遍历 R 中的日期列表。
第一步是dbplyr
在取消嵌套之前呈现查询。大概是这样的:
for(date in c("20191101", "20191102")){
table_name = paste0("bigquery-public-data.google_analytics_sample.ga_sessions_",date)
remote_table = tbl(bigquery_connection, from = table_name)
remote_table = remote_table %>%
filter(! (geoNetwork.networkDomain %like% "%google%")) %>%
select(fullVisitorId, visitId, date, visitStartTime, hits, geoNetwork.networkDomain) %>%
distinct()
}
然后调用show_query(remote_table)
应该产生与以下内容等效的内容。但它不会完全相同,因为dbplyr
编写代码的方式与人类不同。
SELECT DISTINCT fullVisitorId, visitId, date, visitStartTime, hits, geoNetwork.networkDomain
FROM 'bigquery-public-data.google_analytics_sample.ga_sessions_20191101'
WHERE NOT(geoNetwork.networkDomain LIKE "%google%")
第二步,调用自定义的unnest函数”
remote_table = unnest(remote_table,
select_columns = c("fullVisitorId", "visitId", "date", "visitStartTime", "geoNetwork.networkDomain"),
array_column = "hits",
unnested_columns = c("page.pagePath", "time")
)
然后调用show_query(remote_table)
应产生以下结果:
SELECT fullVisitorId, visitId, date, visitStartTime, geoNetwork.networkDomain, position, un.page.pagePath, un.time,
FROM (
the_query_from_the_first_step
) AS src
CROSS JOIN UNNEST(src.hits) AS un WITH OFFSET position
这可能是我所能提供的帮助,因为我没有一个 bigquery 环境来在自己身上测试它。您可能必须调整自定义unnest
函数以使其与您的上下文完全匹配。希望以上内容足以让您入门。