首页 > 解决方案 > teradata 有没有办法从另一个表中替换一行中的多个字符串?

问题描述

我有两张桌子CustomerRoad_AB

客户表数据:

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

Road_AB 数据:

text abb
NW   NEW
HV   Heaven

我的要求是CustomerRoad_AB. 一行中可能有多个字符串需要更新。

更新后的预期结果:

Customer表数据:

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

标签: teradata

解决方案


这里棘手的部分是您将不得不将列的任意子串加入到您的Road_ab表中,这无疑会导致各种令人头疼的问题。值得庆幸的是,Teradata 有这个很棒strtok_split_to_table的功能,它允许您将记录中的列拆分为分隔符上的 MULTIPLE 记录。所以我们可以分割India NW成两条记录IndiaNW在空格字符上分割。然后我们可以 join 并使用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表,然后经历字符串聚合的痛苦。

还值得注意的是,如果您的AddCustomer大小不合适,这可能会失败。看起来您正在用较大的单词替换较小的单词,如果这些单词超出了列的大小,那么基于此 SELECT 的 INSERT 将会失败。


推荐阅读