我正在使用dbplyr在SQL Server中编写和运行查询,并且想要应用条件化的mutate。可以使用ifelse
或使用case_when
来完成。使用ifelse
时查询有效,但使用case_when
时抛出异常。
问题似乎出在这两个命令被翻译成的SQL语法中。 case_when
语法似乎不是有效的SQL。您能告诉我原因以及如何解决吗?还是这是一个错误?
# libraries
library(DBI)
library(dplyr)
library(dbplyr)
# establish connection to database table
connection_string = "database.specific.string"
# mine looks something like "DRIVER=...; Trusted_Connection=...; DATABASE=...' SERVER=..."
db_connection = dbConnect(odbc::odbc(), .connection_string = connection_string)
my_table = tbl(db_connection, from = my_table_name)
# attempted query
tmp = my_table %>%
mutate(new_col = case_when(col1 == col2 ~ "a",
col1 != col2 ~ "b"))
# check SQL code for query
show_query(tmp)
生成的SQL查询为:
SELECT
col1, col2,
CASE
WHEN CONVERT(BIT, IIF(col1 = col2, 1.0, 0.0))) THEN ('a')
WHEN CONVERT(BIT, IIF(col1 <> col2, 1.0, 0.0))) THEN ('b')
END AS new_col
FROM my_database.my_table_name
运行此代码会引发错误
在需要条件的上下文中在“ THEN”附近指定的非布尔类型的表达式
但是ifelse
查询可以按预期工作:
# attempted query
tmp = my_table %>%
mutate(new_col = ifelse(col1 == col2, "a", "b"))
# check SQL code for query
show_query(tmp)
生成的SQL查询为:
SELECT
col1, col2,
CASE
WHEN (CONVERT(BIT, IIF(col1 = col2, 1.0, 0.0))) = TRUE) THEN ('a')
WHEN (CONVERT(BIT, IIF(col1 = col2, 1.0, 0.0))) = FALSE) THEN ('b')
END AS new_col
FROM my_database.my_table_name
请注意,在两种情况下,SQL语法都是使用show_query
生成的。始终使用translate_sql
生成SQL代码可以产生更简洁的SQL语法,但这不是在服务器上运行的语法。
其他人还会得到这些SQL查询吗?关于什么是错误以及如何解决此问题的任何建议?
发布为issue on the tidyverse,并获悉已经开发了一种解决方案,用于将case_when(..., TRUE ~ "b")
转换为ELSE 'b'
(here)。
但是,因为这不能解决导致此异常的语法。对问题进行了编辑,以重点关注引起问题的语法。
发布为issue on dbplyr。 Christophe Dervieux(cderv)的答复指出,原因似乎是SQL服务器需要像case_when
那样对ifelse
进行特殊翻译。
同时,用户可以使用多个ifelse
或if_else
语句。
答案 0 :(得分:0)
仅仅是因为您的dplyr语法有点错误?
尝试一下
# attempted query
tmp = my_table %>%
mutate(new_col = case_when(col1 == col2 ~ "a",
col1 == 'TRUE' ~ "b"
# alternatively col1 == 1 ~ "b"
))