Как использовать EXTRACT через dbplyr при подключении к базе данных Oracle

Возьмите этот запрос:

SELECT EXTRACT(month FROM order_date) "Month"
  FROM orders

(упрощенный пример из официального документа оракула)

Как бы вы подошли к интеграции таких EXTRACT операций, описанных выше, в dbplyr цепочку?

Я открыт для любого другого обходного пути (даже уродливого / дорогостоящего), чтобы извлечь месяц на стороне сервера.


person Moody_Mudskipper    schedule 22.11.2017    source источник
comment
mutate(Month = sql('extract(month from order_date)') работал у меня.   -  person pentandrous    schedule 10.04.2018


Ответы (2)


Более элегантно:

tbl(con, "orders") %>% mutate(Month = extract(NULL %month from% order_date))

В результате получается следующий SQL (ANSI SQL):

EXTRACT( MONTH FROM "order_date")

Этот трюк работает, потому что имена операторов (которые находятся между знаками процента) буквально переводятся в SQL. NULL исчезает (в отличие от NA).

person Fabianius    schedule 24.03.2018
comment
Это будет очень полезно, спасибо. Эта функция не очень подробно документирована, но ее можно увидеть в примерах ?dbplyr::translate_sql - person Moody_Mudskipper; 24.03.2018

Тем временем я кое-что придумал.

Ожидаемый результат данного примера будет получен, выполнив это:

con <- ROracle::dbConnect(drv, username, password, dbname) # your connection parameters
dplyr::tbl(con,"orders") %>%
  extract_o("Month","order_date",append = FALSE,force_upper_case = FALSE)

Вот код функции, я включил некоторые параметры для принудительного использования столбцов в верхнем регистре (по умолчанию) и для добавления нового столбца к существующим (по умолчанию). Имя нового столбца может быть определено или по умолчанию будет названо как тип значения, которое вы хотите извлечь.

#' use Oracle EXTRACT function
#' 
#' Will add a column to the table, containing extracted value,
#' optionally returns only this column
#' @param data tbl_lazy object
#' @param what type of data to extract
#' @param from column to extract from
#' @param new_col name of new column
#' @param append keep existing columns,
#' FALSE ditches them and keep only extracted column
#' @param force_upper_case make new column name uppercase
extract_o <-function(data, what, from, new_col = what,
                     append = TRUE,force_upper_case = TRUE) {
  allowed <- c("day","month","year","hour","minute","second",
                     "timezone_hour","timezone_minute",
                     "timezone_region","timezone_abbr")
  assertthat::assert_that(
    tolower(what) %in% allowed,
    msg=paste("Choose 'what' among",
              paste0("'",allowed,"'",collapse=", ")))
  if(force_upper_case) new_col <- toupper(new_col)
  tbl_query <- as.character(dbplyr::sql_render(data)) # previous query
  append_sql <- if(append)
    paste0(paste(colnames(data),collapse=", "),", ") else ""
  query <- paste0("SELECT ", append_sql,                         # initial cols or none
                  "EXTRACT(",what," FROM ",from,") \"",new_col,  # new col
                  "\" FROM (",tbl_query,")")                     # previous query
  dplyr::tbl(data$src$con,sql(query))
}
person Moody_Mudskipper    schedule 22.11.2017