2016-11-04 6 views
1

Я пытаюсь сгенерировать SQL-запрос с несколькими встроенными переменными с помощью sprintf.R: список переменных смешанного типа sprintf

Я хранил SQL (большой) с параметрами как %s в виде отдельного файла, а затем читал его изнутри r. Чтобы улучшить удобочитаемость, я создал помощника:

fillSQLQuery <- function(query, params){ 
    #' fill query with params 
    do.call(sprintf, as.list(c(query, params))) 
} 

Мои параметры - это даты, факторы и строки. Когда я передаю их непосредственно функции, мои даты заменяются целым числом, а мой коэффициент - с его индексом (?). С другой стороны, когда я конвертирую весь вектор с as.character, он пытается обработать все элементы в строке как даты и вернуть NA или неправильные результаты для всех не-строк).

do.call(sprintf, 
     as.list(c(query,  
     c(as.character(startDateSequence[1]), # POSix DATE 
      as.character(endDateSequence[1]), # POSix DATE  
      lotTypes[1], id_list[1]))))   # string, factor 

Единственный способ решить, что я нашел до сих пор, - это вручную преобразовать даты и типы в символы заранее. Тем не менее, мне интересно, если есть какой-либо «ясно» способ сделать это, как-то просто и надежно, как питоны:

'query {p1}, {p2}'.format(p1=X, p2=Y) 
+0

Это почти невозможно работать без хотя бы небольшого примера вашего вектора 'params'. Пожалуйста, сделайте минимальный воспроизводимый пример. – Gregor

+1

Я имею в виду, что с этой функцией, как вы даже передаете 'params' в, как вектор? Как выглядит вектор, прежде чем вы запустите 'as.character' на нем - он, вероятно, перепутается, как только вы используете' c() 'на объектах разных типов. – Gregor

+0

Вы правы оба раза - я добавил пример вектора, чтобы быть более ясным, и да - по какой-то причине я предположил, что вектор R поддерживает смешанный тип данных в виде списков, но это не так. Простая замена вектора со списком решить проблему: fillSQLQuery (запрос, список (startDateSequence [1], endDateSequence [1], lotTypes [1], ID_LIST [1])) –

ответ

2

Хорошо, вы не предоставили воспроизводимый пример, но ваша цель ясна, так вот код должен был обеспечить, чтобы сделать это хороший пример (самодостаточным и воспроизводимые):

x1 = Sys.Date() # Date 
x2 = Sys.time() # POSIX datetime 
x3 = "hello" # character 
x4 = factor("world", levels = c("world", "something")) # factor 

qry = "Select %s, %s, %s, %s from blah" 

Теперь о том, что установка установлена, мы можем работать над решением. list естественная структура для проведения элементов различных классов:

params = list(x1, x2, x3, x4) 

И мы можем изменить вашу функцию, чтобы преобразовать каждый элемент списка для character перед использованием sprintf:

fillSQLQuery = function(query, params){ 
    params = lapply(params, as.character) 
    do.call(sprintf, c(query, params)) 
} 

fillSQLQuery(qry, params) 
# [1] "Select 2016-11-05, 2016-11-05 17:19:29, hello, world from blah" 
Смежные вопросы