Teradata:基于定界符解析字符串,然后返回在解析的字符串中找到的不同值

时间:2019-09-25 16:13:41

标签: sql teradata teradata-sql-assistant

我有一个现有的数据库,其中包含一列,我们可以将其称为“ PACKAGES”,并将其值串联成一个字符串,每行还包含一个对应的“ ACCOUNT_ID”值。

Row 1: ACCOUNT_ID = 123, PACKAGES = 'AAA BBB CCC '
Row 2: ACCOUNT_ID = 456, PACKAGES = ' DDD DDD AAA BBB CCC CCC EEE'
Row 3: ACCOUNT_ID = 789, PACKAGES = 'FFF ZZZ QQQ QQQ'

我需要生成让我为每个帐户划定包裹字段的代码,以便1)代码在SPACE领先于第2行中的字符时识别出代码,以及2)仅显示各个帐户的不同包裹。在结果答案集中,ACCOUNT_ID字段没有区别。

ACCOUNT_ID | PACKAGES    
123        | AAA
123        | BBB
123        | CCC
456        | DDD
456        | AAA
456        | BBB
456        | CCC
456        | EEE
789        | FFF
789        | ZZZ
789        | QQQ

我尝试在下面在网上找到的一些示例代码中使用REGEXP,但是我不知道在哪里可以从正在使用的数据库中输入表名,我也不知道是否可以可以用以下任何代码替换“ PACKAGES”字段,以获取所需信息。

SELECT * FROM TABLE (

    REGEXP_SPLIT_TO_TABLE ('SMART PHONES','MOTOROLA&MICROSOFT&GOOGLE&APPLE','&','C')

    RETURNS (OUTKEY VARCHAR(10), TOKEN_NDX INTEGER, TOKEN VARCHAR(10))

) AS T1;

2 个答案:

答案 0 :(得分:1)

regexp_split_to_table的语法总是让我发疯。

select
*
from
table (regexp_split_to_table(<your db.table>.account_id,<your db.table>.packages, ' ','c')
returns   (account_Id integer, tok_num integer,package varchar(100))) as t

哪个会给你:

account_Id  tok_num package
    123     1       AAA
    123     2       BBB
    123     3       CCC

要仅获取不同的值,可以运行:

select
 distinct account_id,package
from
table (regexp_split_to_table(<your db.table>.account_id,<your db.table>.packages, ' ','c')
returns   (account_Id integer, tok_num integer,package varchar(100))) as t
order by account_id,package

编辑:

在您对超出长度的评论之后,我做了一些深入探讨。与REGEXP_SPLIT_TO_STRING相比,STRTOK_SPLIT_TO_STRING似乎能够处理更长的字符串,包括Clob(不要问我为什么...)。因此,从@DNoeth偷偷摸摸,可以尝试以下方法:

with cte as (
select account_id,
cast(packages as clob)
from your_table)
SELECT
  DISTINCT account_Id, package
FROM TABLE (StrTok_Split_To_Table(cte.account_id,cte.packages, ' ')
     RETURNS (account_Id INTEGER, tok_num INTEGER,package VARCHAR(100))) AS t

我破解了一个巨大的字符串(60k),并用它测试了此逻辑,它对我有用。请注意,必须强制转换为Clob,否则会出现相同的错误。

答案 1 :(得分:1)

添加到@Andrew的答案中。

将数据传递给表运算符的最简单方法是使用通用表表达式:

WITH cte AS
 ( -- whatever you need to prepare your data
   SELECT * FROM your_table 
 )
SELECT
  DISTINCT account_Id, package
FROM TABLE (RegExp_Split_To_Table(cte.account_id,cte.packages, ' ','c')
     RETURNS (account_Id INTEGER, tok_num INTEGER,package VARCHAR(100))) AS t

但是在您的情况下,不需要RegEx,还有另一个UDF基于定界符分割字符串:

WITH cte AS
 ( -- whatever you need to prepare your data
   SELECT * FROM your_table 
 )
SELECT
  DISTINCT account_Id, package
FROM TABLE (StrTok_Split_To_Table(cte.account_id,cte.packages, ' ')
     RETURNS (account_Id INTEGER, tok_num INTEGER,package VARCHAR(100))) AS t