【问题标题】:Can dplyr function work connected with SQL server?dplyr 函数可以与 SQL server 连接工作吗?
【发布时间】:2021-02-17 15:27:50
【问题描述】:

我在 SQL Server 数据库中有一个表,我想用 R 包中的 dbplyr/dplyr 来操作这个表。

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)

我该如何解决这个问题?

附言当我首先将“day”转换为 tibble 后应用 dplyr 函数时,它可以工作。但是,我想直接应用 dplyr 函数,而不是转换为 tibble,因为它既耗时又耗内存。

【问题讨论】:

  • 不,dplyr 不能这样做。但dbplyr 可能可以。
  • 该代码与dbplyr一起应用,但它有同样的问题

标签: r sql-server dplyr dbplyr


【解决方案1】:

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

注意错误信息中的SQL代码包含:

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

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

解决此问题的两种方法:

  1. 在变异前使用arrange
  2. 通过指定leadorder_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)

但是,您似乎也只想在每个 stockCode 中使用 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)

【讨论】:

  • 非常感谢您,Simon,现在效果很好!
  • 但是,在您的第一个解决方案中将 logDate 更改为 stockCode 变量 (arrange, order_by) 后,它工作得非常好
  • 在你的第二个解决方案中,它工作得很好,输出没有问题,但是有这个警告消息: ORDER BY is ignored in subqueries without LIMIT i Do you need to movearrange() later in管道还是使用 window_order() 代替?
  • 对于第二种解决方案,您可能希望在lead 函数中使用order_by 参数而不是arrange
  • 我还有一个问题,Simon,你能看看吗?
猜你喜欢
  • 1970-01-01
  • 2022-06-28
  • 1970-01-01
  • 1970-01-01
  • 2012-02-29
  • 1970-01-01
  • 2021-09-21
  • 1970-01-01
相关资源
最近更新 更多