Можете ли вы назвать смоделированные ленивые таблицы dbplyr?

dbplyr имеет несколько очень полезных функций моделирования, поэтому вы можете писать запросы, не подключенные к какой-либо реальной базе данных, но я не могу получить фактические имена таблиц ни в одном из запросов, которые я пишу таким образом. Все их имена просто `df`, и я не могу их потом изменить. На самом деле я нигде не вижу `df` ни в объекте запроса, ни в его атрибутах (у него их нет), так что теперь я понятия не имею, как dbplyr вообще обрабатывает имена таблиц.

MWE:

library(dbplyr)
library(dplyr, warn.conflicts = FALSE)
library(magrittr)
library(purrr, warn.conflicts = FALSE)

query <- tbl_lazy(df = mtcars)
query %$% names(ops)
#> [1] "x"    "vars"
show_query(query)
#> <SQL>
#> SELECT *
#> FROM `df`

# The actual data frame is stored in the object under the name `x`, but
# renaming it has no effect, unsurprisingly (since it wasn't named `df`
# anyway)
query %<>% modify_at("ops", set_names, "mtcars", "vars")
query %$% names(ops)
#> [1] "mtcars" "vars"
show_query(query)
#> <SQL>
#> SELECT *
#> FROM `df`

Мой вариант использования, кстати, заключается в том, что мне нужно запускать SQL-запросы в другой системе с фактическим доступом к серверу, поэтому я хотел бы иметь R-скрипты, которые создают синтаксис SQL, готовый к запуску в этой системе, даже если R может' т подключиться к нему. Создание пустой фиктивной базы данных со структурой реальной вещи (имена таблиц и столбцов, типы столбцов, но без строк) является вариантом, но, очевидно, было бы проще просто использовать эти симуляции в свободной форме, если только SQL может быть сгенерирован готовым для вырезания и вставки. (lazy_frame() выглядел более подходящим для таких несуществующих таблиц, но, знаете ли, на самом деле это просто оболочка для tbl_lazy(tibble()), так что точно такая же проблема с именем `df`.)

Создано 12 декабря 2019 года с помощью пакета reprex (v0.3.0)


person DHW    schedule 12.12.2019    source источник
comment
Я по-прежнему считаю, что это недооцененный вариант использования (c.f. stackoverflow.com/q/49078185/6636442 ), но не имеют хорошего решения. Я попробовал трюк sqlite в памяти, который позволяет вам называть начальные таблицы, но отображаемый sql требует много ручного редактирования, чтобы наложить имена таблиц на подзапросы.   -  person steveo'america    schedule 05.02.2020


Ответы (1)


Я не знаю, как переименовать смоделированные таблицы. Согласно документации, важным моментом функций simulate_* является проверка перевода базы данных без фактического подключения к базе данных.

При подключении к удаленной таблице dbplyr использует базу данных, схему и имя таблицы, определенные с помощью tbl(). Он также извлекает имена столбцов. Из-за этого я бы рекомендовал разработку в среде, где R может подключаться к базе данных. Рассмотрим следующее:

# simulated
df_sim = tbl_lazy(mtcars, con = simulate_mssql())
df_sim %>% head(5) %>% show_query()

# output
<SQL>
SELECT TOP(5) *
FROM `df`

# actual
df = tbl('db_table_name', con = database_connection_object)
df %>% head(5) %>% show_query()

# output
<SQL>
SELECT TOP(5) col1, col2, col3
FROM "database"."db_table_name"

Не только df заменяется именем таблицы, но и * в смоделированном запросе заменяется именами столбцов во втором запросе.

Один из вариантов, который вы можете рассмотреть, если важно генерировать сценарии SQL с помощью моделирования, — это преобразование в текст, замена и обратное преобразование. Например:

df_sim = tbl_lazy(mtcars, con = simulate_mssql())
query = df_sim %>% head(5) %>% as.character()
query = gsub("`df`", "[db].[schema].[table]", query)

# write query out to file
writeLines(query, "file.sql")
# OR create a remote connection
remote_table = tbl(db_connection, sql(query))

remote_table %>% show_query()
# output
<SQL>
SELECT TOP(5) *
FROM [db].[schema].[table]
person Simon.S.A.    schedule 12.12.2019
comment
Как только вы соедините две таблицы, вы обнаружите, что обе они называются df, и этот хак не сработает. - person steveo'america; 05.02.2020
comment
Хороший вопрос @steveo'america. Я бы порекомендовал попробовать подстановку перед соединением, сразу после команды tbl_lazy для каждой таблицы. - person Simon.S.A.; 06.02.2020