Импорт серии файлов .CSV, содержащих одно поле, при добавлении дополнительных «известных» данных в другие поля.

0

У меня есть процесс, который создает файл csv, который содержит ОДИН набор значений, которые мне нужно импортировать в поле в таблице базы данных MySQL. Этот процесс создает определенное имя файла, которое идентифицирует значения других полей в этой таблице. Например, имя файла T001U020C075.csv будет разбито следующим образом:

T001 = Test 001
U020 = User 020
C075 = Channel 075

Файл содержит одну строку данных, разделенных запятыми, для всех результатов теста для этого пользователя на определенном канале, и это может выглядеть примерно так: 12.555, 15.275, 18.333, 25.000... (есть сотни, может быть, тысячи, результаты на пользователя, за канал).

То, что я хочу сделать, это импортировать непосредственно из файла CSV, добавляя информацию о поле из имени файла, чтобы он выглядел примерно так:

insert into results (test_no, user_id, channel_id, result) values (1, 20, 75, 12.555)

Я попытался использовать "Bulk Insert", но, похоже, хочет импортировать все поля, в которых каждый ROW является записью. Конечно, я мог бы зайти в каждый файл и преобразовать строку в столбец и добавить данные из имени файла в столбцы, предшествующие результатам, но это будет очень трудоемкая задача, поскольку есть сотни файлов, которые были созданы и необходимы для импорта.

Я нашел несколько "импортных CSV" решений, но все они предполагают, что все данные находятся в файле. Очевидно, это не...

Процесс, который сгенерировал эти файлы, не может быть изменен (да, я спросил). Даже если он может быть изменен, он будет обеспечивать только правильный формат, и необходимо проанализировать исторические данные. И новый формат займет значительно больше места.

Я могу ограничить использование MATLAB или MySQL Workbench для импорта данных.

Любая помощь приветствуется. боб

Теги:
mysql-workbench

1 ответ

0

Возможный SQL-подход для получения данных, загружаемых в таблицу, заключался бы в следующем:

LOAD DATA LOCAL INFILE '/dir/T001U020C075.csv'
INTO TABLE results 
FIELDS TERMINATED BY '|'
LINES TERMINATED BY ','
( result )
SET test_no    = '001'
  , user_id    = '020'
  , channel_id = '075'

;

Нам нужна запятая, чтобы быть разделителем строк. Мы можем указать некоторый символ, которому мы гарантируем, что мы не будем отделяться от разделителя полей. Таким образом, мы получаем LOAD DATA чтобы увидеть одно "поле" на каждой "линии".

(Если в конце файла нет конечной запятой, после последнего значения нам нужно проверить, чтобы убедиться, что мы получаем последнее значение (последняя "строка", поскольку мы говорим LOAD DATA, чтобы посмотреть на файл.)


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

-- parse filename components into user-defined variables
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(f.n,'T',-1),'U',1)   AS t
     , SUBSTRING_INDEX(SUBSTRING_INDEX(f.n,'U',-1),'C',1)   AS u
     , SUBSTRING_INDEX(f.n,'C',-1)                          AS c
     , f.n                                                  AS n
  FROM ( SELECT SUBSTRING_INDEX(SUBSTRING_INDEX( i.filename ,'/',-1),'.csv',1) AS n 
           FROM ( SELECT '/tmp/T001U020C075.csv' AS filename ) i 
       ) f
  INTO @ls_u
     , @ls_t
     , @ls_c
     , @ls_n
;

пока мы тестируем, мы, вероятно, хотим увидеть результат разбора.

-- for debugging/testing
SELECT @ls_t
     , @ls_u
     , @ls_c 
     , @ls_n
;     

А затем часть о выполнении фактического заявления LOAD DATA. Мы должны снова указать имя файла. Нам нужно убедиться, что мы используем одно и то же имя файла...

LOAD DATA LOCAL INFILE '/tmp/T001U020C075.csv'
INTO TABLE results
FIELDS TERMINATED BY '|'
LINES TERMINATED BY ','
( result )
SET test_no    = @ls_t
  , user_id    = @ls_u
  , channel_id = @ls_c

;

(Клиенту потребуется разрешение на чтение файла CSV)


К сожалению, мы не можем обернуть это в процедуру, потому что выполнение инструкции LOAD DATA не допускается из сохраненной программы.

Некоторые правильно отметили бы, что в качестве обходного пути мы могли бы скомпилировать/построить пользовательскую функцию (UDF) для выполнения внешней программы, и процедура могла бы вызвать это. Лично я бы этого не сделал. Но это альтернатива, которую мы должны упомянуть, учитывая ограничения.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню