如何选择所有非空列?

时间:2019-09-24 09:53:30

标签: sql r vertica

我正在使用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)
}

如何使我的解决方案更快?

2 个答案:

答案 0 :(得分:0)

这里似乎有两个独立的部分:

1)建立SELECT列表
您可以在脚本或存储过程/函数中执行此操作,但我认为这不会对性能产生太大影响。

2)检查列是否具有NULL值
这是您性能最高的地方。可以尝试以下几种方法:

  • 某些数据库在其数据字典中存储列是否为NULLable。您可能可以使用它来过滤出NULLable列。链接:OracleTeradata

  • 尝试其他计算,而不是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]

您已经在查询循环中的数据。这样会更有效率,因为运行的每个查询都有开销。