我正在使用VERTICA(SQL)
软件包将查询发送到R ODBC
。我正在寻找一种快速的解决方案,该解决方案将从表A中选择所有非空列并将其放入新表B中。
我认为自己创建和运行的效率非常低下,但是我不知道如何使其更快。如果MAX
不为null,则该函数对表中的每一列取最大值,并将其选中。将所有内容放入一个查询不会有太大变化,因为Vertica
是一个列数据库。
reduce_width <- function(in_name, out_name) {
query_in <- paste('SELECT * FROM', in_name, 'LIMIT 1;', sep = ' ')
vertica_answer <- dbGetQuery(conn, query_in)
var_names <- colnames(vertica_answer)
lenght <- length(var_names)
var_names <- as.data.frame(var_names, stringsAsFactors = F)
var_names$is_null <- 0
for(i in 1:lenght){
name <- as.character(var_names[i,1])
query_max <- paste('SELECT MAX(',name,') from', in_name,';', sep = ' ')
max_value <- dbGetQuery(conn, query_max)
if(is.na(max_value[1,1])){
var_names$is_null[i]<-0
} else {
var_names $is_null[i]<-1
}
}
not_null_collumns <-var_names %>% filter(is_null==1) %>% select(var_names)
not_null_collumns <- (as.character(t(not_null_collumns$var_names)))
query_front <- 'SELECT'
for(i in 1:(length(not_null_collumns)-1)) {
query_front <- paste(query_front, not_null_collumns[i],',', sep = ' ')
}
query_front <- paste(query_front,
not_null_collumns[length(not_null_collumns)], sep = ' ')
query_back <- paste('into', out_name, 'from', in_name , sep = ' ')
query_create <- paste(query_front, query_back, sep = ' ')
dbSendQuery(conn, query_create)
}
如何使我的解决方案更快?
答案 0 :(得分:0)
这里似乎有两个独立的部分:
1)建立SELECT列表
您可以在脚本或存储过程/函数中执行此操作,但我认为这不会对性能产生太大影响。
2)检查列是否具有NULL值
这是您性能最高的地方。可以尝试以下几种方法:
某些数据库在其数据字典中存储列是否为NULLable
。您可能可以使用它来过滤出NULLable列。链接:Oracle,Teradata
尝试其他计算,而不是MAX
。也许COUNT
会更快,因为它不必对值进行排序/比较。逻辑将是这样的:
CASE
WHEN (
COALESCE(COUNT(*), 0) - -- Get total row count
COALESCE(COUNT(col1), 0) -- Get # non-NULL values in col1
) = 0 THEN 'No Nulls'
ELSE 'Has Nulls'
END AS col1_NullValuesCheck
您可以进行一次COUNT(*)
计算,将其存储并将其与COUNT(colX)
值进行比较。
EXISTS
运算符:SELECT EXISTS(SELECT 1 FROM MyTable WHERE col1 IS NULL)
我同意上一个发布者的观点,最好将其组合成一个查询。
答案 1 :(得分:0)
您应该一次查询所有内容:
query_all <- paste('SELECT * FROM', in_name, ';', sep = ' ')
vertica_answer <- dbGetQuery(conn, query_all)
Vertica_sub <- vertica_answer[ , colSums(is.na(vertica_answer)) == 0]
#or just non null columns
non_null_cols <- names(verica_answer)[colSums(is.na(vertica_answer)) == 0]
您已经在查询循环中的数据。这样会更有效率,因为运行的每个查询都有开销。