使用 dplyr 过滤 SQLite 数据库时,是否应避免使用“|”?
When filtering an SQLite database with dplyr, should `|` be avoided?
在 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
如果你这样做
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
但第一个 "term" 没有放在一起。那么由于 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
我不确定如果在 SQL 的情况下有多个条件,为什么 dplyr 不隐式地为您添加括号,因为它似乎确实为 [=28= 正确地评估了它们].您可能会考虑 filing this as an "issue" 看看官方对此的立场是什么,因为对我来说它看起来像是一个错误。
在 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
如果你这样做
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
但第一个 "term" 没有放在一起。那么由于 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
我不确定如果在 SQL 的情况下有多个条件,为什么 dplyr 不隐式地为您添加括号,因为它似乎确实为 [=28= 正确地评估了它们].您可能会考虑 filing this as an "issue" 看看官方对此的立场是什么,因为对我来说它看起来像是一个错误。