【发布时间】:2018-08-23 03:51:24
【问题描述】:
我正在使用 dbplyr 在 SQL Server 中编写和运行查询,并希望应用条件变异。这可以使用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)。
但是,因为这没有解决导致此异常的语法。编辑问题以关注导致原因的语法。
更新 2
以issue on dbplyr 发布。来自 Christophe Dervieux (cderv) 的响应表明原因似乎是 SQL 服务器需要对 case_when 进行特殊翻译,就像对 ifelse 一样。
同时,用户可以使用多个ifelse 或if_else 语句。
【问题讨论】:
-
我也尝试使用
ifelse而不是case_when这给出:CASE WHERE (CONVERT(BIT, IIF(col1 = col2, 1.0, 0.0))) = TRUE) THEN ('a')确实有效。所以也许这是一个错误? -
有一个ongoing PR 建议用
ELSE子句替换WHEN(TRUE)。这应该可以解决您的问题。
标签: r sql-server dbplyr