RMySQL - Выберите данные из базы данных, где значение существует в списке - PullRequest
0 голосов
/ 15 февраля 2019

Я пытаюсь извлечь данные из базы данных только там, где имя существует в уже существующем фрейме данных.Я не уверен, как включить список в мою выбранную статистику.

БОНУС: Мне нужно переформатировать все данные в более дружественный формат.

library(RMySQL)
library(DBI)

db_con <- dbconnect(RMySQL::MySQL(),
          username: "user",
          password: "1234",
          dbname = "test")

df <- as.data.frame(tbl(db_con, sql("SELECT name, loc, type, value FROM data"))

Это читает всю таблицуданных.Мне нужно ограничить то, что входит на основе поля имени.

 df$names <- "cat, hamster"

 name_filter <- df$names

Текущий df:

#    name    loc     type    val
1    cat     ab12    a       1
2    cat     1233    a       0
3    dog     ab12    a       0
4    dog     45ff    b       1
5    hamster ab12    a       1
6    hamster 45ff    b       0

Желаемый вывод БЕЗ чтения всей таблицы в: SELECT * WHERE name IN name_filter?

#    loc    type    cat    hamster
1    ab12   a       1      1
2    1233   a       0      0
3    45ff   b       0      0

РЕДАКТИРОВАТЬ: Попытка использовать библиотеку (изменить) для данных не так хорошо.Я, вероятно, делаю это неправильно, хотя ... В настоящее время я использую усеченную базу данных с примерно 45 миллионами строк.(Полная база данных составляет около 300 миллионов.)

 cast(df, loc+type ~ name, value = "val")

, что приводит к очень длинной паузе, за которой следует ошибка «Агрегация требует fun.aggregate: длина используется по умолчанию», за которой следует то, что кажетсябесконечная пауза.

EDIT2: список имен состоит из пары сотен элементов и меняется каждый раз, когда его запрашивают.В имени есть десятки тысяч значений.

EDIT3: я нашел это в другом потоке, пытаясь сгенерировать оператор выбора на основе списка значений.Я не уверен, что это полезно, поскольку я тоже не могу заставить его работать.

list <- list$Name
sel <- "SELECT name, loc, type, val FROM data WHERE name IN (%s)"
sql1 <- sprintf(sel,paste(list, collapse =","))

yields: 
"SELECT name, loc, type, val FROM data WHERE name IN (dog,cat,hamster,square,triangle,circle,ball,horse,lion)

EDIT4: пытаюсь использовать следующее, но получаю ошибку о синтаксисе для MariaDB.Есть ли разница в операторах выбора между MySQL и MariaDB?

list <- df$Name
sqlqry <- "SELECT data.loc, data.type"
for (i in 1:length(list)) {
  sqlqry <- paste0(sqlqry, sprintf(", MAX(CASE WHEN data.name = '%s' 
                           THEN 1 ELSE 0 END) AS %s",list[i], list[i]))
}
sqlqry <- paste0(sqlqry, "FROM 
data
GROUP BY 
data.loc
, data.type")

test <- dbSendQuery(db_con, sqlqry)

1 Ответ

0 голосов
/ 15 февраля 2019

Этот запрос даст вам нужный результат.

SELECT 
   data.loc
 , data.type
 , MAX(CASE WHEN data.name = 'cat' THEN 1 ELSE 0 END) AS cat
 , MAX(CASE WHEN data.name = 'hamster' THEN 1 ELSE 0 END) AS hamster
FROM 
 data
GROUP BY 
   data.loc
 , data.type

Чтобы избежать сканирования всей таблицы, вам понадобится (покрывающий) индекс.Этот индекс должен сделать выбор намного быстрее с помощью вышеуказанного запроса.

ALTER TABLE data ADD INDEX <index_name> (loc, type, name)
, ALGORITHM=INPLACE
, LOCK=NONE

, ALGORITHM=INPLACE, LOCK=NONE будет работать только на движке InnoDB.он является частью онлайновой библиотеки DLL InnoDB , которая не допускает простоев для таблицы.

...