dplyr 函数可以连接 SQL 服务器吗?

Can dplyr function work connected with SQL server?

我在 SQL 服务器数据库中有一个 table,我想在 R 包中用 dbplyr/dplyr 操作这个 table。

library(odbc)
library(DBI)
library(tidyverse)

con <- DBI::dbConnect(odbc::odbc(),
                      Driver    = "SQL Server", 
                      Server    = "xx.xxx.xxx.xxx",
                      Database  = "stock",
                      UID       = "userid",
                      PWD       = "userpassword")

startday = 20150101
day = tbl(con, in_schema("dbo", "LogDay")) 

我在连接到远程数据库后尝试了这个简单的 dplyr 函数,但只是失败并显示错误消息。

day %>% 
  mutate(ovnprofit = ifelse(stockCode == lead(stockCode,1),lead(priceOpen,1)/priceClose, NA)) %>% 
  select(logDate,stockCode, ovnprofit)

我该如何解决这个问题?

p.s。当我先将 'day' 转换为 tibble 后应用 dplyr 函数时,它起作用了。但是,我想直接应用 dplyr 函数,而不是转换为 tibble,因为它既耗时又占用内存。

问题很可能与 lead 函数有关。在 R 中,数据集有顺序,但在 SQL 中,数据集是无序的,需要明确指定顺序。

请注意,错误消息中的 SQL 代码包含:

LEAD("stockCode", 1.0, NULL) OVER ()

OVER 之后的括号中没有任何内容向我暗示 SQL 在这里需要一些东西。

解决此问题的两种方法:

  1. 通过在 mutate
  2. 之前使用 arrange
  3. 通过指定 lead
  4. order_by 参数
# approach 1:
day %>% 
  arrange(logDate) %>%
  mutate(ovnprofit = ifelse(stockCode == lead(stockCode,1),
                            lead(priceOpen,1)/priceClose,
                            NA)
                     ) %>% 
  select(logDate,stockCode, ovnprofit)

# approach 2:
day %>% 
  mutate(ovnprofit = ifelse(stockCode == lead(stockCode,1, order_by = 'logDate'),
                            lead(priceOpen,1, order_by = 'logDate')/priceClose,
                            NA)
                     ) %>% 
  select(logDate,stockCode, ovnprofit)

但是,您似乎只想 lead 每个股票代码。这可以通过 group_by 来完成。我会推荐以下内容:

output = day %>% 
  group_by(stockCode) %>%
  arrange(logDate) %>%
  mutate(next_priceOpen = lead(priceOpen, 1)) %>%
  mutate(ovnprofit = next_priceOpen / priceClose)
  select(logDate,stockCode, ovnprofit)

如果您使用 show_query(output) 查看生成的 SQL,您应该会看到类似于以下内容的 SQL OVER 子句:

LEAD(priceOpen, 1.0, NULL) OVER (PARTITION BY stockCode ORDER BY logDate)