【问题标题】:RMySQL - Select data from db where value exists in listRMySQL - 从列表中存在值的数据库中选择数据
【发布时间】:2019-07-09 00:15:17
【问题描述】:

我正在尝试仅在名称存在于已存在的数据框中的数据库中提取数据。我不确定如何将列表包含到我的选择语句中。

奖励:我需要将所有数据重新格式化为更友好的格式。

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

编辑:尝试对数据使用 library(reshape) 并不顺利。不过,我可能做错了......我目前正在提取一个包含大约 4500 万行的截断数据库。 (完整的db在3亿左右。)

 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 的 select 语句有区别吗?

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)

【问题讨论】:

  • 您的输出更改将是一个数据透视表,而您将在 MySQL 中找到解决方案,在您的应用程序中更容易做到。
  • “在你的应用程序中更容易做到”@danblack 好吧,我认为 MySQL 更容易,除了在应用程序中进行旋转需要双内存来保存完整的表(尝试使用数百万或数十亿关闭记录这很可能不是这里的情况,但仍然)结果和您正在构建枢轴的临时结果。除了loc, type, name 上的(覆盖)索引将使其(照明)快速。
  • 几亿条记录.....目前正在玩弄 reshape 以将其转换为我想要的格式......它在时间上并不顺利。大声笑如果我能让 select 语句正确运行,它只会拉入 4000 万条左右的记录?
  • "几亿条记录....." 在该表之外添加该大小的索引也可能需要一段时间.. 你能发布SHOW CREATE TABLE &lt;table&gt; 和 MySQL 版本吗SELECT VERSION(); .. 对于动态 MySQL 透视查询,您很可能需要loc, type, name 上的索引

标签: mysql r rmysql


【解决方案1】:

此查询将为您提供所需的结果。

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 引擎。它是InnoDB's online DLL 的一部分,它可以使桌子没有停机时间。

【讨论】:

  • “猫”和“仓鼠”的例子非常通用。所发生的是输入了一个名字列表。这个列表有几百个名字,每次都不一样。(我会添加该信息的问题。)
  • 您需要在应用程序中生成, 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部分。
  • 收到以下错误:.local(conn, statement, ...) 中的错误:无法运行语句:您的 SQL 语法有错误;检查与您的 MariaDB 服务器版本相对应的手册,以在第 1 行的 'ball, MAX(CASE WHEN data.name = 'square' THEN 1 ELSE 0 E' 附近使用正确的语法
猜你喜欢
  • 2020-03-13
  • 2012-11-13
  • 2016-04-14
  • 1970-01-01
  • 2017-10-21
  • 2012-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多