bigrquery - Error: No matching signature for operator - for argument types: DATE, FLOAT64

bigrquery - Error: No matching signature for operator - for argument types: DATE, FLOAT64

filter() 按日期计算并使用函数提供该日期时,我看到预期错误:

library(tidyverse)
library(bigrquery)

table1 %>% 
  filter(date > as.character(today() - 730)) %>% 
  tally()

# Error: No matching signature for operator - for argument types: DATE, FLOAT64. 
Supported signatures: INT64 - INT64; NUMERIC - NUMERIC; FLOAT64 - FLOAT64 at [29:29] [invalidQuery]

但是当日期以字符串形式提供时它工作正常

table1 %>%
  filter(date > '2018-04-11') %>% 
  tally()

#          n
#      <int>
#  623451234

我可以确认 as.character(today() - 730)'2018-04-11' 是一样的

> identical(as.character(today() - 730), '2018-04-11')
[1] TRUE

以下变通方法没问题,但对于较大的代码库会变得混乱:

date_from <- as.character(today() - 730)

table1 %>% 
  filter(date > date_from) %>% 
  tally()

问题

为什么我们在通过 as.character(today() - 730) 之类的函数向 filter() 提供日期时看到错误,但在通过字符串提供日期时却看不到错误?

备注

虽然在您的问题中没有提及,但您已经用 dbplyr 标记了它。如果您使用 dbplyr 那么问题是由于 dbplyr 如何从 R 翻译成数据库语言(在您的情况下是大查询)。

dbplyr 有一系列进行转换的内置翻译(例如 filter 被翻译成 WHERE 子句)。这些翻译能够根据您的示例从变量中查找值:

date_from <- as.character(today() - 730)
table1 %>% filter(date > date_from)

但无法判断子功能是评估、翻译还是保持原样。因此,根据 this 文档,dbplyr 保留任何 'unknown' 函数原样。这意味着

table1 %>% filter(date > as.character(today() - 730))

可能会被翻译成

SELECT ...
FROM ...
WHERE date > as.character(today() - 730)

这会导致错误,因为这不是数据库的有效语法。

您可以使用 show_query():

查看翻译
table1 %>% filter(date > as.character(today() - 730)) %>% show_query()

This question 询问一个非常相似的问题 - 翻译是为他们正在使用的函数定义的,而不是为充当包装器的自定义函数定义的。能够定义自定义翻译将解决这两个问题,但目前这似乎不可能。

有两个解决方法:

  1. dbplyr documentation 您可以使用 sql() 插入原始 SQL 字符串(不会被翻译)。
  2. 您可以编写自己的 return 自定义 table 定义的函数。请参阅 的 "Creating custom functions" 部分。