创建连续整数,然后使用 dplyr 创建存储在 sqlserver 中的表的索引

lok*_*art 5 indexing r dplyr

我正在对存储在 sqlserver 中的一些大表进行一些数据处理,这些表创建索引有时会减少运行某些 R 脚本所需的时间。我尝试使用 的mutate功能dplyr创建一个idx具有连续编号的新列 ( ),然后将该idx列用作索引。但是 mutate 功能似乎不起作用并且不断给我这个错误:

> tbl(channel,'tbl_iris') %>% mutate(idx=1:n())
Error in from:to : NA/NaN argument
In addition: Warning message:
In 1:n() : NAs introduced by coercion\
Run Code Online (Sandbox Code Playgroud)

现在我正在做一些对我来说似乎很愚蠢的事情,以“绕过”上述错误消息:

iris <- tbl(channel,'tbl_iris') %>% 
  collect %>%
  mutate(idx=1:n())

try(db_drop_table(channel,'##iris'))
copy_to(channel,iris,'##iris',temporary=FALSE)
db_create_index(channel,'##iris',columns='idx')
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来做到这一点?谢谢!

更新 01

mutate(idx = row_number())按照@Phil 的建议进行了尝试,但它不起作用并显示以下错误消息:

> tbl(channel,'##iris') %>%
+   mutate(idx=row_number())
Error: <SQL> 'SELECT  TOP 10 "Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species", row_number() OVER () AS "idx"
FROM "##iris"'
  nanodbc/nanodbc.cpp:1587: 42000: [Microsoft][ODBC SQL Server Driver][SQL Server]The function 'row_number' must have an OVER clause with ORDER BY. 
> tbl(channel,'##iris') %>%
+   arrange(Species) %>%
+   mutate(idx=row_number())
Error: <SQL> 'SELECT  TOP 10 "Sepal.Length", "Sepal.Width", "Petal.Length", "Petal.Width", "Species", row_number() OVER (ORDER BY "Species") AS "idx"
FROM (SELECT *
FROM "##iris"
ORDER BY "Species") "kwtundzona"'
  nanodbc/nanodbc.cpp:1587: 42000: [Microsoft][ODBC SQL Server Driver][SQL Server]The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified. 
Run Code Online (Sandbox Code Playgroud)

更新 02

我尝试了@Moody_Mudskipper 建议的方法,它似乎有效

> try(db_drop_table(channel,'##iris'))
[1] 0
> copy_to(channel,iris,'##iris',temporary=FALSE)
> tbl(channel,'##iris') %>% head(.,1)
# Source:   lazy query [?? x 5]
# Database: Microsoft SQL Server 11.00.6251[dbo@WCDCHCMS9999\CMSAH_DC7_999/data_xx_yyy]
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
         <dbl>       <dbl>        <dbl>       <dbl> <chr>  
1         5.10        3.50         1.40       0.200 setosa 
> 
> DBI::dbSendQuery(channel,"ALTER TABLE ##iris ADD idx INT IDENTITY(1,1) NOT NULL")
<OdbcResult>
  SQL  ALTER TABLE ##iris ADD idx INT IDENTITY(1,1) NOT NULL
  ROWS Fetched: 0 [complete]
       Changed: 0
> db_create_index(channel,'##iris',columns='idx')
[1] 0
Warning message:
In new_result(connection@ptr, statement) : Cancelling previous query
> tbl(channel,'##iris') %>% head(.,5)
# Source:   lazy query [?? x 6]
# Database: Microsoft SQL Server 11.00.6251[dbo@WCDCHCMS9999\CMSAH_DC7_999/data_xx_yyy]
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species   idx
         <dbl>       <dbl>        <dbl>       <dbl> <chr>   <int>
1         5.10        3.50         1.40       0.200 setosa      1
2         4.90        3.00         1.40       0.200 setosa      2
3         4.70        3.20         1.30       0.200 setosa      3
4         4.60        3.10         1.50       0.200 setosa      4
5         5.00        3.60         1.40       0.200 setosa      5
Run Code Online (Sandbox Code Playgroud)

我将尝试修改我的脚本,看看与我之前更愚蠢的方法相比,这是否会带来类似的性能提升。

除了如下所示的错误消息,我希望一切按计划进行。

Warning message:
In new_result(connection@ptr, statement) : Cancelling previous query
Run Code Online (Sandbox Code Playgroud)

Moo*_*per 3

据我所知,您无法将列添加到服务器端的现有表中,dbplyr但是对于像这样的简单查询,它很容易使用DBI::dbSendQuery以达到所需的效果。以下行将创建一个 id 列:

DBI::dbSendQuery(channel, "ALTER TABLE tbl_iris ADD ID INT IDENTITY(1,1) NOT NULL")
Run Code Online (Sandbox Code Playgroud)

dplyr::db_create_index然后您可以使用或发送另一个查询来创建索引:

 DBI::dbSendQuery(channel, "CREATE INDEX id ON tbl_iris (id);")
Run Code Online (Sandbox Code Playgroud)