使用dplyr过滤SQLite数据库时,应该避免使用`|`

时间:2015-01-29 00:45:41

标签: r sqlite filter dplyr

在使用R中的dplyr过滤SQLite数据库时遇到了一些意外行为。以下是我看到的示例:

library(dplyr)

# Some test data
df <- tbl_df(data.frame(
  v1 = c('a', 'b', 'a', 'b'),
  v2 = c('b', 'a', 'a', 'b'),
  v3 = month.abb[1:4]))

db <- copy_to(src_sqlite('example.sqlite', create = TRUE), df)

filter(df, v1 == 'a' | v2 == 'a', v3 == 'Jan') 
# Source: local data frame [1 x 3]
#
#   v1 v2  v3
# 1  a  b Jan

filter(db, v1 == 'a' | v2 == 'a', v3 == 'Jan')
# Source: sqlite 3.8.6 [example.sqlite]
# From: df [2 x 3]
# Filter: v1 == "a" | v2 == "a", v3 == "Jan" 
#
#  v1 v2  v3
# 1  a  b Jan
# 2  a  a Mar

我对使用数据库感到很陌生,所以我觉得我错过了一些显而易见的事情,因为这可以按照预期的方式在过滤器中使用|

filter(db, v1 == 'a', v3 == 'Jan') 
# Source: sqlite 3.8.6 [example.sqlite]
# From: df [1 x 3]
# Filter: v1 == "a", v3 == "Jan" 
#
#   v1 v2  v3
# 1  a  b Jan

使用dplyr在数据库中工作时应该避免|吗?

更新 dplyr issue #934

1 个答案:

答案 0 :(得分:4)

如果你这样做

filter(db, v1 == 'a' | v2 == 'a', v3 == 'Jan') %>% show_query()

你会看到它变成

<SQL>
SELECT "v1", "v2", "v3"
FROM "df"
WHERE "v1" = 'a' OR "v2" = 'a' AND "v3" = 'Jan'

所以|被翻译为OR,但第一个&#34;术语&#34;不是在一起。然后,因为AND的优先级高于OR,所以它与运行

相同
WHERE "v1" = 'a' OR ("v2" = 'a' AND "v3" = 'Jan')

您可以添加自己的括号以避免问题

filter(db, (v1 == 'a' | v2 == 'a'), v3 == 'Jan') %>% show_query()
# <SQL>
# SELECT "v1", "v2", "v3"
# FROM "df"
# WHERE ("v1" = 'a' OR "v2" = 'a') AND "v3" = 'Jan'

filter(db, (v1 == 'a' | v2 == 'a'), v3 == 'Jan')
# Source: sqlite 3.8.6 [example.sqlite]
# From: df [1 x 3]
# Filter: (v1 == "a" | v2 == "a"), v3 == "Jan" 
# 
#   v1 v2  v3
# 1  a  b Jan

我不确定为什么dplyr没有为你隐式添加括号,如果你在SQL的情况下有多个条件,因为它似乎正在为data.frame正确评估它们。您可能会考虑filing this as an "issue"看看官方的立场是什么,因为对我而言,这看起来像是一个错误。