Есть ли способ в teradata заменить множественную строку в строке из другой таблицы? - PullRequest
0 голосов
/ 09 января 2019

У меня есть две таблицы Customer и Road_AB

Данные таблицы клиентов:

id Add
1  India NW
2  Poland NW HV
3  ASIA HV

Данные Road_AB:

text abb
NW   NEW
HV   Heaven

Мое требование - выполнить обновление таблицы Customer из Road_AB. В строке может быть несколько строк, которые необходимо обновить.

Ожидаемый результат после обновления:

Customer данные таблицы:

id Add
1  India NEW
2  Poland NEW Heaven
3  ASIA Heaven

1 Ответ

0 голосов
/ 09 января 2019

Сложность в том, что вам придется присоединиться к произвольной подстроке столбца к вашей таблице Road_ab, которая, несомненно, вызывает все виды царапин на голове. К счастью, Teradata имеет эту замечательную функцию strtok_split_to_table, которая позволит вам разбить столбец в записи на НЕСКОЛЬКО записей на разделителе. Таким образом, мы можем разделить India NW на две записи India и NW, разделив пробел символом. Затем мы можем присоединиться и использовать XMLAGG() для объединения этих разделенных строк вместе. Эти функции позволяют нам сохранять порядок и записывать ключи на протяжении всего процесса.

Вот рабочий пример с использованием данных вашего образца:

CREATE MULTISET VOLATILE TABLE Customer(
   id  INTEGER  
  ,Addf VARCHAR(30) NOT NULL
) ON COMMIT PRESERVE ROWS;
INSERT INTO Customer(id,Addf) VALUES (1,'India NW');
INSERT INTO Customer(id,Addf) VALUES (2,'Poland NW HV');
INSERT INTO Customer(id,Addf) VALUES (3,'ASIA HV');

CREATE MULTISET VOLATILE TABLE Road_AB(
   textf CHAR(2)  
  ,abb  VARCHAR(30) NOT NULL
) ON COMMIT PRESERVE ROWS;
INSERT INTO Road_AB(textf,abb) VALUES ('NW','NEW');
INSERT INTO Road_AB(textf,abb) VALUES ('HV','Heaven');

SELECT splitCustomer."id",  TRIM(TRAILING ',' FROM (XMLAGG(TRIM(COALESCE(road_ab.abb, splitCustomer.token))|| '' ORDER BY splitCustomer.TokenNum) (VARCHAR(10000), CHARACTER SET UNICODE)))
FROM 
    (
        SELECT * 
        FROM TABLE (STRTOK_SPLIT_TO_TABLE(customer.id, customer.addf, ' ')
         RETURNS (id integer 
         ,tokennum INTEGER
         ,token VARCHAR(30) CHARACTER SET UNICODE)
         ) AS dt
    ) splitCustomer
    LEFT OUTER JOIN road_ab
        ON trim(splitCustomer.token) = trim(road_ab.textf)
GROUP BY 1;

DROP TABLE customer;
DROP TABLE Road_ab;


+----+-------------------+
| id |        add        |
+----+-------------------+
|  3 | ASIA Heaven       |
|  2 | Poland NEW Heaven |
|  1 | India NEW         |
+----+-------------------+

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

Стоит также отметить, что это может завершиться ошибкой, если ваш столбец Add в Customer не имеет соответствующего размера. Похоже, вы заменяете слова меньшего размера словами большего размера, и если они превышают размер столбца, то ваша INSERT, основанная на этом SELECT, потерпит неудачу.

...