Эксперт по SQLite может улучшить это решение, но вы можете сделать это с помощью одного запроса, выполнив его сразу после создания merged_table
:
dbGetQuery(con, "INSERT INTO merged_table SELECT
letters,left_num,right_num,left_num+right_num row_sum FROM
(SELECT let letters,left_table.num left_num, right_table.num right_num FROM
left_table LEFT OUTER JOIN right_table USING (let))")
Это вроде уродливый SQL, я полагаю, но он работает. Если вам нужно добавить более двух столбцов, вы можете построить часть запроса на добавление столбцов, используя paste
в R, если это необходимо.
Другие вещи, которые нужно исследовать, - это добавление дополнительного столбца с помощью ALTER TABLE
, а затем массовое обновление пакетами. Я играл с этим в течение минуты или двух, но не мог заставить это работать, но это определенно не означает, что это невозможно.
EDIT
Следующий код создает желаемый результат. В данный момент я как бы тороплюсь (выходя из двери), поэтому цикл while
выдает ошибку, потому что цикл достигает конца данных до того, как будет достигнуто условие выхода, поэтому в последний раз у вас есть пустой data.1
фрейм данных, который вызывает ошибку в bind.data
. Но если вы выполните последний запрос, вы увидите, что все данные были вставлены.
library(RSQLite)
left <- data.frame(let = letters[rep(1:4, each = 5)], num = 1:20)
right <- data.frame(let = letters[rep(1:4, each = 5)], num = 21:40)
conn <- dbConnect(dbDriver("SQLite"), dbname = "sotemp.db")
conn.copy <- dbConnect(dbDriver("SQLite"), dbname = "sotempCopy.db")
dbWriteTable(conn, "left_table", left, row.names = F)
dbWriteTable(conn, "right_table", right, row.names = F)
dbGetQuery(conn, "CREATE TABLE merged_table1 (letters TEXT, left_num INTEGER, right_num INTEGER)")
dbGetQuery(conn.copy, "CREATE TABLE merged_table2 (letters TEXT, left_num INTEGER, right_num INTEGER, rowSum INTEGER,
rowMean REAL)")
dbGetQuery(conn, "INSERT INTO merged_table1 SELECT * FROM left_table LEFT OUTER JOIN right_table USING (let)")
res <- dbSendQuery(conn, "SELECT letters, left_num, right_num FROM merged_table1")
while (!dbHasCompleted(res)) {
data.1 <- fetch(res,n=5)
data.1 <- cbind(data.1,rowSums(data.1[,2:3]),rowMeans(data.1[,2:3]))
colnames(data.1)[4:5] <- c("rowSum","rowMean")
dbGetPreparedQuery(conn.copy, "INSERT INTO merged_table2 (letters, left_num, right_num,rowSum, rowMean) VALUES
(?, ?, ?, ?, ?)", bind.data = data.1)
}
dbClearResult(res)
dbGetQuery(conn.copy, "SELECT * FROM merged_table2")
Это ни в коем случае не идеально. Я надеюсь, что другие будут проходить мимо и редактировать / добавлять к этому. Несколько замечаний о том, почему ваше решение не работает.
Сначала INSERT
добавляет новые строки в таблицу. Вы, похоже, ожидали, что он изменит значения в столбце, что обычно делается с помощью UPDATE
, что может стать громоздким.
Во-вторых, я не уверен, что отдельные подключения для чтения / записи вам что-нибудь покупают. SQLite
не поддерживает полный параллелизм чтения / записи, даже при использовании отдельных соединений. Поэтому, пока вы не очистите результаты SELECT
, вы будете получать ошибки блокировки при попытке записи.
В-третьих, стратегия, которую я использовал здесь для пакетной обработки, заключалась в создании двух отдельных БД, циклическом просмотре результатов SELECT
в первом, создании новых столбцов в R и затем INSERT
результирующих данных во втором дб.