Я использую 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-запросы? Есть предложения относительно того, что не так и как это исправить?
Обновлено
Размещено как проблема на tidyverse и проинформировано, что решение уже разработано для case_when(..., TRUE ~ "b")
переводится на ELSE 'b'
(здесь).
Однако, поскольку это не касается синтаксиса, вызывающего это исключение. Вопрос отредактирован, чтобы сосредоточиться на синтаксисе, который является причиной.
Обновление 2
Размещено как проблема на dbplyr. В ответе Кристофа Дервье (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')
, что действительно работает. Так, может быть, это ошибка? - person Simon.S.A.   schedule 23.08.2018WHEN(TRUE)
предложениемELSE
. Это должно решить вашу проблему. - person cderv   schedule 27.08.2018