Как выбрать все ненулевые столбцы? - PullRequest
0 голосов
/ 24 сентября 2019

Я отправляю запрос на VERTICA(SQL), используя пакет R ODBC.Я ищу быстрое решение, которое выберет все ненулевые столбцы из таблицы A и поместит их в новую таблицу B.

Я создал и функционирую, что, на мой взгляд, крайне неэффективно, но я незнать, как сделать это быстрее.Функция принимает максимальное значение для каждого столбца в таблице и выбирает его, если MAX не равно нулю.Помещение всего в один запрос не сильно изменится, потому что 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 голосов
/ 24 сентября 2019

Вы должны запросить все сразу:

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]

Вы уже запрашиваете данные в цикле.Это более эффективно, поскольку для каждого выполняемого запроса есть издержки.

0 голосов
/ 24 сентября 2019

Здесь, кажется, есть две отдельные части:

1) Построить список SELECT
Вы можете сделать это в своем скрипте или хранимой процедуре / функции, но я неНе думаю, что это сильно повлияет на производительность.

2) Проверьте, имеет ли столбец значение NULL
Именно здесь вы получите наибольшее снижение производительности.Вот пара идей:

  • Некоторые базы данных хранят, является ли столбец 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)

Я согласен с предыдущим постером, вероятно, было бы лучше объединить это в один запрос.

...