使用 R 从 SQL 数据库中获取 mytable 的 summary() 而无需将其写入我的 R 会话

Get summary() of mytable from SQL database with R without writing it to my R session

我想用 R 从 SQL 数据库中获取 table, 我可以做到,

df <- sqlQuery(channel, "select * from scheme.mytable1")

但是后来我想得到一个table的汇总函数(我想看table的汇总)

summary(df)

我可以通过连接到 SQL 数据库并将 table 带到我的 R 会话来做到这一点 (在 R 控制台中将其视为 table 作为 df)然后获取摘要(df)

但我想做的是,在不将其写入我的 R 会话的情况下查看其摘要 因为 table 太大了。 (百万列)我无法将其写入我的 R 会话。

但我只想查看其列的摘要。

summary(sqlQuery(channel, "select * from scheme.mytable1"))

我想做类似上面的事情(但是代码不起作用,只是为了说明我的目的)

我该怎么做?任何包裹?任何功能?部署者?

谢谢!

您可以做的一件事是利用 dplyr::tbl 从数据源创建一个远程 table,然后编写您自己的 summary 方法来在数据库上完成大部分计算.这可能是这样的:

library(dplyr)
library(tidyr)

# create a connection to table using dplyr, use dummy data 
# in memory SQLite here,in practice would do df <- tbl(con,  "mytable1")
con <- DBI::dbConnect(RSQLite::SQLite(), dbname = ":memory:")
copy_to(con, ggplot2::diamonds, "diamonds")
diamonds_db <- tbl(con,  "diamonds")

# create custom summary method for the connection
summary.tbl_SQLiteConnection <- function(object, ...) {
  suppressMessages({
    nums <- object %>% 
      summarise_if(
        is.numeric, 
        # can put whatever functions here
        # these should work for most DBs
        list(Min = min, Max = max, Mean = mean)
      ) %>% 
      collect() %>% 
      pivot_longer(everything()) %>% 
      mutate(name = stringi::stri_reverse(name)) %>% 
      separate(name, into = c("fun", "var"), sep = "_", extra = "merge") %>% 
      mutate_at(vars(var, fun), stringi::stri_reverse) %>% 
      mutate(val = paste0(fun, ": ", round(value, 2))) %>% 
      split(.$var) %>% 
      lapply(`[[`, "val")
    other_nms <- object %>% 
      select_if(~!is.numeric(.x)) %>% 
      head(1) %>% 
      collect() %>% 
      names()
    other <- lapply(other_nms, function(x) {
      x <- ensym(x)
      object %>% 
        group_by(!!x) %>% 
        tally() %>%
        arrange(desc(n)) %>%
        # only show top 10 values
        head(10) %>%
        collect() %>% 
        mutate(tmp = paste0(!!x, ": ", n)) %>% 
        pull(tmp)
    })
  })
  names(other) <- other_nms
  lst <- c(other, nums)
  # format similar to summary.data.frame 
  mat <- matrix(NA_character_, max(sapply(lst, length)), length(lst))
  for (i in seq_along(lst)) {
    for (j in seq_along(mat[, i])) {
      mat[j, i] <- lst[[i]][j]
    }
  }
  colnames(mat) <- names(lst)
  rownames(mat) <- rep("", dim(mat)[1])
  structure(mat, class = "table")
}

summary(diamonds_db)
#> cut              color    clarity    carat     depth       price        table       x          y          z         
#> Fair: 1610       D: 6775  I1: 741    Min: 0.2  Min: 43     Min: 326     Min: 43     Min: 0     Min: 0     Min: 0    
#> Good: 4906       E: 9797  IF: 1790   Max: 5.01 Max: 79     Max: 18823   Max: 95     Max: 10.74 Max: 58.9  Max: 31.8 
#> Ideal: 21551     F: 9542  SI1: 13065 Mean: 0.8 Mean: 61.75 Mean: 3932.8 Mean: 57.46 Mean: 5.73 Mean: 5.73 Mean: 3.54
#> Premium: 13791   G: 11292 SI2: 9194                                                                                 
#> Very Good: 12082 H: 8304  VS1: 8171                                                                                 
#>                  I: 5422  VS2: 12258                                                                                
#>                  J: 2808  VVS1: 3655                                                                                
#>                           VVS2: 5066 

我在 table 上尝试过这个方法,因为它太大而无法放入内存并且它起作用了。此函数 不完全 匹配 summary.data.frame 给出的内容,但应该是一个开始。