2013-09-11 3 views
1

Я пытаюсь извлечь blob из старой таблицы MySQL и создать для нее новую таблицу, стремясь достичь первой нормальной формы. Однако скрывать данные, уже находящиеся в базе данных из blob, в несколько строк в новой таблице, нелегко.MySQL Преобразование столбца базы данных из Blob в отдельные части

Что является самым простым способом достижения преобразования с помощью команды SQL?

Родитель Таблица:

CREATE TABLE TEST.People (
    `id` INT AUTO_INCREMENT, 
    `age` INT, 
    `height` INT, 
    `weight` INT , 
    `variations` BLOB DEFAULT NULL, 
    PRIMARY KEY (`id`), 
); 

Новая таблица:

CREATE TABLE TEST.Variations (
    `id` INT AUTO_INCREMENT, 
    `chr` INT, 
    `start` INT, 
    `stop` INT , 
    `type` ENUM('SNP','INDEL','CNV') DEFAULT NULL, 
    PRIMARY KEY (`id`), 
); 

При запуске SELECT, идентификатор, отклонения от TEST.People; я получаю:

+----+----------------------------------------------------------------------------------------------------------------------+ 
| id | variations                           | 
+----+----------------------------------------------------------------------------------------------------------------------+ 
| 3 | xp t !3:124093754-124467278/CNVt 7:78030601-79638023/CNV               | 
| 6 | xp                             | 
| 9 | xp                             | 
| 12 | xp t !1:84289718-85466763/CNV                      | 
| 15 | xp                             | 
| 18 | xp                             | 
| 21 | xp                             | 
| 24 | xp                             | 
| 27 | xp                             | 
| 30 | xp t !10:166909544-166909544/SNPt !2:66903445-66903445/SNPt !2:166897864-166897864/CNVt !7:6892788-6892788/SNP  | 
+----+----------------------------------------------------------------------------------------------------------------------+ 

Так что я хочу, чтобы таблица TEST.Variations иметь после преобразования заключается в следующем:

+----+-----+-----------+-----------+----------+ 
| id | chr | start  | stop  | type  | 
+----+-----+-----------+-----------+----------+ 
| 3 | 3 | 124093754 | 124467278 | CNV  | 
| 3 | 7 | 78030601 | 79638023 | CNV  | 
| 12 | 1 | 84289718 | 85466763 | CNV  | 
| 30 | 10 | 166909544 | 166909544 | SNP  | 
| 30 | 2 | 66903445 | 66903445 | SNP  | 
| 30 | 2 | 166897864 | 166897864 | CNV  | 
| 30 | 7 | 6892788 | 6892788 | SNP  | 
+----+-----+-----------+-----------+----------+ 
+0

это должно быть сделано с некоторыми типами регулярных выражений, скорее всего. Вопрос: '' 'всегда приходит перед вашими строками, которые нужно рубить в отдельные столбцы, когда строки повторяются в текущем блобе? и имеет ли отношение '!' какое-либо отношение к миграции или его следует игнорировать, как в примере? – amaster

+2

Это будет сложно сделать и сделать чек на чистом языке запросов MySQL; правильный инструмент для разбора столбца blob 'changes' - это язык обработки строк, такой как PHP или PERL. –

+0

@ amaster507 - в настоящее время MySQL не реализует функции REGEX_REPLACE. –

ответ

1

Прежде всего две вещи:

  1. You имеют несогласованность в данных для id 3. Нет ! непосредственно перед 7:.... Я надеюсь, что это просто опечатка

    xp t !3:124093754-124467278/CNVt 7:78030601-79638023/CNV 
                ^^ 
    
  2. Если вы хотите иметь auto_increment столбец в целевой таблице, то вы схема должна выглядеть как этот

    CREATE TABLE variations 
    (
        `var_id` INT NOT NULL AUTO_INCREMENT, 
        `id` INT, -- id from People goes here and it's not UNIQUE 
        `chr` INT, 
        `start` INT, 
        `stop` INT , 
        `type` ENUM('SNP','INDEL','CNV') DEFAULT NULL, 
        PRIMARY KEY (`var_id`) 
    ); 
    

Теперь вы можете данные передачи от People до Variations таблица с запросом

INSERT INTO variations (id, chr, start, stop, type) 
SELECT id, 
     SUBSTRING_INDEX(variation, ':', 1) chr, 
     SUBSTRING_INDEX(SUBSTRING_INDEX(variation, '-', 1), ':', -1) start, 
     SUBSTRING_INDEX(SUBSTRING_INDEX(variation, '-', -1), '/', 1) stop, 
     SUBSTRING_INDEX(variation, '/', -1) type 
    FROM 
(
    SELECT p.id, SUBSTRING_INDEX(SUBSTRING_INDEX(p.variations, 't !', n.n), 't !', -1) variation 
    FROM 
    (
    SELECT id, SUBSTR(variations, 9) variations 
     FROM people 
    WHERE variations LIKE 'xp t !%' 
) p CROSS JOIN 
    (
    SELECT a.N + b.N * 10 + 1 n 
     FROM 
     (SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) a 
    ,(SELECT 0 AS N UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) b 
     ORDER BY n 
) n 
    WHERE n.n <= 1 + (LENGTH(p.variations) - LENGTH(REPLACE(p.variations, 't !', '')))/3 
    ORDER BY id 
) q 
ORDER BY id, chr, start, stop, type; 

Примечание: этот запрос разделит до 100 вариантов на id. Если вам нужно больше или меньше, вы можете отрегулировать ограничение, отредактировав внутренний подзапрос с помощью псевдонима n, который на лету выводит таблицу чисел.

Результат:

 
| VAR_ID | ID | CHR |  START |  STOP | TYPE | 
|--------|----|-----|-----------|-----------|------| 
|  1 | 3 | 3 | 124093754 | 124467278 | CNV | 
|  2 | 3 | 7 | 78030601 | 79638023 | CNV | 
|  3 | 12 | 1 | 84289718 | 85466763 | CNV | 
|  4 | 30 | 10 | 166909544 | 166909544 | SNP | 
|  5 | 30 | 2 | 166897864 | 166897864 | CNV | 
|  6 | 30 | 2 | 66903445 | 66903445 | SNP | 
|  7 | 30 | 7 | 6892788 | 6892788 | SNP | 

Вот SQLFiddle демо

Смежные вопросы