【问题标题】:dplyr sql joinsdplyr sql 连接
【发布时间】:2018-07-21 04:10:00
【问题描述】:

考虑以下 SQL:

    SELECT D.product_name
      FROM business.payment P
 LEFT JOIN dim.product_name D 
        ON D.product_id = P.product_id

查询返回支付表中的 product_names 列表,并基于连接。

如何在不拉入内存的情况下在 dplyr 中复制这样的内容?我正在处理数据库连接。

我尝试了以下方法,但无济于事:

product_name <- 
  business %>% 
  tbl('dim_product') 

business %>% 
  tbl('payment') %>% 
  left_join(product_name, by = 'product_id') %>% 
  select(product_name) %>% 
  collect()

我搜索了很多,似乎没有人解决这个问题。

谢谢!

【问题讨论】:

  • R 将所有对象存储在内存中。因此,如果您使用dplyr,那么您将在对象上使用它,因此在内存中使用它。话虽如此,您可以在dplyr 中使用任意 SQL,例如tbl(my_db_extract_now_in_memory, sql("SELECT * FROM flights")) 但它总是会在记忆中。
  • 我正在尝试使用 dplyr 严格执行此操作。在collect() 触发之前,懒惰不应该将它们带入记忆中。
  • dplyr 中做这一切没问题,但我只是说一旦提取它就会在内存中。请注意,这与通过 R 通过任何其他方式(例如 RODBC)查询数据库没有什么不同。它不在内存中的一种方法是,如果您使用 RPostgresRODBC 等发送 SQL 查询并仅使用它在在数据库中创建一个新表并且永远不会将数据导出到 R。
  • 没关系。关键是要在最终拉取之前防止这种情况发生,因为有大量数据。

标签: sql r dplyr


【解决方案1】:

这是事后的一段时间,但也许您仍在寻找或好奇基于动词的dplyr 选项。我正在为我的工作解决同样的问题,并遇到了您(某种)未回答的问题。当我使用 DBIodbc 包对 MSSQL 数据库运行它时,以下对我有用。

我在加入之前从表中选择了感兴趣的列,因为这通常是查询数据库时的最佳做法。 dplyr 连接函数默认会进行自然连接,因此您可能不必显式提供 by 参数。

db_con <- DBI::dbConnect(
  drv = odbc::odbc(),
  dsn = <data source name>
)

db_con %>%
  tbl("table1") %>%
  select(col1, col2, col3) %>%
  left_join(
    db_con %>% tbl("table2") %>% select(col3,  col4, col5)
  )

【讨论】:

    【解决方案2】:

    你可以在dplyr中使用任意SQL:

    tbl(my_data, sql("SELECT * FROM flights"))
    

    请注意,这与通过 R 通过任何其他方式(例如 RODBC)查询数据库没有什么不同。

    当然,一旦通过查询将提取的数据始终导入到 R 中,它就会在内存中。它根本不会在内存中的一种方法是,如果您使用 RPostgresRODBC 等发送 SQL 查询并仅使用它在数据库中创建一个新表并且从未将数据导出到 R .

    【讨论】:

    • 是的,但我正在尝试使用 dplyr 执行此操作,因此我只能使用一种语言。 How would something like this be replicated in dplyr without pulling into memory?
    • @PhillipBlack 你在说什么?我的答案 is dplyr 中的代码我回答了你关于在不将其拉入内存的情况下执行此操作的问题。就像我说的,你在dplyr 中使用任意SQL,就像我的例子一样。请参阅 ?tbl 并阅读精美手册 cran.r-project.org/web/packages/dplyr/dplyr.pdfcran.r-project.org/web/packages/dplyr/vignettes/databases.html
    • @PhillipBlack 所以,回顾一下,正如你提到的,dplyr 可以通过惰性等到最后一秒,即它只将最终提取(而不是中间表)拉入内存,这正是发生在我答案的代码中。为了绝对没有任何东西被拉入内存,那么(显然)唯一的解决方案是使用RODBC 或任何类似的包将您的数据查询到数据库中新创建的表中,从而完全绕过 R。
    • 我觉得有误会。我试图不使用 any SQL,不管它是用什么包装的。
    • @RasmusLarsen 是的,这会引发数据类型错误。抱歉,已经好几年了。试试这个:download.file(url = "https://ndownloader.figshare.com/files/2292171",destfile = "a.sqlite", mode = "wb"); mammals &lt;- DBI::dbConnect(RSQLite::SQLite(), "a.sqlite"); tbl(mammals, sql("SELECT year, species_id, plot_id FROM surveys"))
    猜你喜欢
    • 1970-01-01
    • 2015-02-14
    • 1970-01-01
    • 1970-01-01
    • 2015-02-09
    • 2021-09-23
    • 2018-09-25
    • 1970-01-01
    相关资源
    最近更新 更多