我希望使用R在本地存储在SQLite数据库中的表上执行多个后续联接.我使用这种方法使内存不受数据(存储为Tibble)的影响,因为有些表大于R允许的单个向量的大小限制. 虽然我设法执行连接并根据每个连接创建一个新表,但我更愿意更新现有的表.

library(DBI)
library(dbplyr)
library(tidyverse)


con <- DBI::dbConnect(RSQLite::SQLite(), 
                      dbname = "test")

dbplyr::copy_nycflights13(con)

dbListTables(con)

加入本地tibble是可行的,但对于我的用例来说,在环境中没有足够的内存来执行此步骤.

# data stored locally
left_join(nycflights13::flights,
          nycflights13::planes,
          by = c("tailnum", "year")) |> 
  left_join(nycflights13::airlines, by = "carrier")

存储在RSQLite数据库中的数据.First Join工作并返回df1,该df1作为新表写入数据库.例如:

# in dplyr /dbplyr
left_join(x = tbl(con, "flights"),
          y = tbl(con, "planes"),
          by = c("tailnum", "year")) |> 
  show_query() |> 
  compute(name = "df1", temporary = F)

无法保存第二个查询,表df1已存在.例如:

left_join(x = tbl(con, "df1"),
          y = tbl(con, "airlines"),
          by = "carrier") |> 
  show_query() |> 
  compute(name = "df1", temporary = F)

有没有办法强制compute()覆盖现有的表?或者,有人能给出如何在SQL Query中编写该代码的建议吗?我try 了以下几种方法:

query <- "
  UPDATE df1
  SET
    name = result.name
  FROM (
    SELECT
      carrier,
      name
    FROM
      df1
    LEFT JOIN
      airlines
    USING
      (carrier)
  ) AS result
  WHERE
    df1.carrier = result.carrier
"

# Execute the update query
dbExecute(con, query)

但我得到的错误是:Error: no such table: df1dbListTables(con)表示df1在数据库中.

怎么啦?

推荐答案

你遇到的一个问题是,你没有在数据库中的df1中定义name;一旦你这样做了,你可以使用"连接时更新".

# setup
library(DBI); library(dplyr)
con <- DBI::dbConnect(RSQLite::SQLite(), dbname = "test")
dbplyr::copy_nycflights13(con)

# for the demo, we'll wipe out `df1` and regenerate it with an empty `name` column
dbExecute(con, "drop table df1")
left_join(x = tbl(con, "flights"),
          y = tbl(con, "planes"),
          by = c("tailnum", "year")) |> 
  mutate(name = NA_character_) |>
  show_query() |> 
  compute(name = "df1", temporary = FALSE)

从这里开始,如果我们try 使用您现有的query进行更新,则会收到错误:

Error: ambiguous column name: name

此外,一旦我们修复了它,我们就会得到very slow的更新(我从来没有足够的耐心让它超过几分钟).从https://stackoverflow.com/a/21074659/3358272开始,

query <- "
UPDATE df1
SET name = (SELECT name
                  FROM airlines
                  WHERE airlines.carrier = df1.carrier) 
where EXISTS (SELECT name
                  FROM airlines
                  WHERE airlines.carrier = df1.carrier)"
dbExecute(con, query)
# [1] 336776

dbGetQuery(con, "select * from df1 limit 10") |> str()
# 'data.frame': 10 obs. of  27 variables:
#  $ year          : int  2013 2013 2013 2013 2013 2013 2013 2013 2013 2013
#  $ month         : int  1 1 1 1 1 1 1 1 1 1
#  $ day           : int  1 1 1 1 1 1 1 1 1 1
#  $ dep_time      : int  517 533 542 544 554 554 555 557 557 558
#  $ sched_dep_time: int  515 529 540 545 600 558 600 600 600 600
#  $ dep_delay     : num  2 4 2 -1 -6 -4 -5 -3 -3 -2
#  $ arr_time      : int  830 850 923 1004 812 740 913 709 838 753
#  $ sched_arr_time: int  819 830 850 1022 837 728 854 723 846 745
#  $ arr_delay     : num  11 20 33 -18 -25 12 19 -14 -8 8
#  $ carrier       : chr  "UA" "UA" "AA" "B6" ...
#  $ flight        : int  1545 1714 1141 725 461 1696 507 5708 79 301
#  $ tailnum       : chr  "N14228" "N24211" "N619AA" "N804JB" ...
#  $ origin        : chr  "EWR" "LGA" "JFK" "JFK" ...
#  $ dest          : chr  "IAH" "IAH" "MIA" "BQN" ...
#  $ air_time      : num  227 227 160 183 116 150 158 53 140 138
#  $ distance      : num  1400 1416 1089 1576 762 ...
#  $ hour          : num  5 5 5 5 6 5 6 6 6 6
#  $ minute        : num  15 29 40 45 0 58 0 0 0 0
#  $ time_hour     : num  1.36e+09 1.36e+09 1.36e+09 1.36e+09 1.36e+09 ...
#  $ type          : chr  NA NA NA NA ...
#  $ manufacturer  : chr  NA NA NA NA ...
#  $ model         : chr  NA NA NA NA ...
#  $ engines       : int  NA NA NA NA NA NA NA NA NA NA
#  $ seats         : int  NA NA NA NA NA NA NA NA NA NA
#  $ speed         : int  NA NA NA NA NA NA NA NA NA NA
#  $ engine        : chr  NA NA NA NA ...
#  $ name          : chr  "United Air Lines Inc." "United Air Lines Inc." "American Airlines Inc." "JetBlue Airways" ...

(侧注:这是denormalizingdf1数据库;如果这是您明确的意图,那么它正在做您想做的事情,尽管在许多数据库讨论中,可能建议/更喜欢保持它的规范化,其中(例如)字符串"United Air Lines Inc."存储在一个16行的承运商和姓名表中,并且在您进行查询时将其连接到您的数据中.这主要是理论上的讨论,尽管以这种方式存储df1.name确实会在数据库中占用更多的空间.)

Sql相关问答推荐

创建每小时重置的序列号

从以前的非空值行中获取值

R中对Arrow duckdb工作流的SQL查询

如何在snowflake中进行SQL的反向填充

每年独特口味的冰淇淋数量

snowflake/SQL嵌套的JSON对象和数组

如何找到一个组合的两个列,这是不是在其他表在ORACLE SQL?

我需要一个regexp_like来只验证字母D或T、数字和管道

使用拆分器将已分组的不同值连接在一起

根据时间、状态和相关行在PostgreSQL中的存在来删除行

SQL递归.硬币兑换问题.-try 使用递归解决硬币找零问题

Grafana SQL 模板变量(值、文本)

Oracle 21c 中的递归查询回顾过go 3 周

Postgresql:在链接表中判断相关表中插入值的条件

更新之前如何获得价值

Oracle函数中无法动态迭代创建的SYS_REFCURSOR

过滤具有一对多关系的两个表之间的数据

Postgres:表的累积视图

如何通过存储过程将 root 的下一个子 node 作为父 node ?

具有关联统计信息 N+1 的 Rails 6 索引资源?