繁体   English   中英

如何将字符串文本中的值转换为表联接的列表-Teradata SQL

[英]How to convert the values in string text into a list for table joins - Teradata SQL

嗨,我对Teradata SQL中的表联接有疑问。 因此,我有一个交易表(T1)和另一个国家/地区映射表(M1)结合在一起。

在事务表(T1)中,还包括(对于表联接):(i)。 SalesOrg代码; (ii)。 售至国家/地区代码

表T1:

    SalesOrg Code  Sold-To Country Cd    Product Code     Trans. Date    Revenue Amt
    0001           ES                    P001             01/08/2019      199.00
    0002           IE                    P002               02/08/2019      399.00
    0002           FR                    P003               02/08/2019      299.00
    0002           IT                    P005               02/08/2019      599.00
    0002           BE                    P002               02/08/2019      399.00
    0002           LU                    P005               02/08/2019      599.00
    0002           NL                    P001               02/08/2019      199.00

对于国家/地区映射表(M1),它看起来像这样:

SalesOrg Code   Reporting Country   Sold-To Country Code    Sold-To Country Name
0001            Spain                null                   null
0002            UK                   IE                     Ireland
0002            UK                   FR                     France
0002            UK                   IT                     Italy
0002            Netherlands          Ex:                    NOT: FR IE IT
.......

我要实现的是根据以下条件联接两个表:

1)。 如果Sold-To Country Code为空,则从销售组织代码中的T1提取所有交易(例如#0001);
2)。 如果Sold-To国家/地区代码为NOT NULL并且不包含“ Ex”,则根据SalesOrg代码和Sold-To国家/地区代码映射来自T1的交易;
3)。 如果“售至”国家/地区代码包含“ Ex”(表示排除),则使用相同的SalesOrg代码映射T1交易,但不包括最后一列中指定的国家/地区代码,例如上面的示例:NOT:FR IE IT。

对于#3条件,我最终希望将字符串文本NOT:FR IE IT中的值转换为列表,以便可以像NOT IN('FR','IE','IT')一样在JOIN中使用它。

最终,我想获得如下结果(最后一列-报告国):

SalesOrg Code  Sold-To Country Cd    Product Code     Trans. Date    Revenue Amt    Reporting Country
0001           ES                    P001             01/08/2019      199.00        Spain
0002           IE                    P002               02/08/2019      399.00      UK
0002           FR                    P003               02/08/2019      299.00      UK
0002           IT                    P005               02/08/2019      599.00      UK
0002           BE                    P002               02/08/2019      399.00      Netherlands
0002           LU                    P005               02/08/2019      599.00      Netherlands
0002           NL                    P001               02/08/2019      199.00      Netherlands

........

有更好的主意吗?

我尝试使用STRTOK_SPLIT_TO_TABLE将FR IE IT值转换为行,并且确实可以创建此类列表。 但是,这不是唯一的情况,其他国家/地区也存在相同的情况,因此,我需要联接条件基于M1表中记录的每一行。

(
CASE WHEN M1.Sold_to_Country_Code LIKE 'Ex%') THEN  (
            SELECT DISTINCT TOKEN
                FROM TABLE (STRTOK_SPLIT_TO_TABLE(1,
                    (SELECT DISTINCT
                    TRIM(BOTH FROM (SUBSTR(M1.Sold_to_Country_Name,INSTR(M1.Sold_to_Country_Name,' ')))) AS Exclude_Country
                    FROM M1
                    WHERE M1.Sold_to_Country_Code LIKE 'Ex%'
                    ),' ')
                      RETURNS (OUTKEY INTEGER,
                      TOKENNUM INTEGER,
                      TOKEN VARCHAR(2) CHARACTER SET UNICODE)
                      ) AS d )
    END  ) 

我在下面尝试过,但是无法正确映射,因为它将与荷兰的国家代码IE FR IT一起重复映射到荷兰。

SELECT DISTINCT
T1.sales_org_cd,
M1.Reporting_Country,
M1.Sold_to_Country_Code,
OREPLACE(TRIM(BOTH FROM (SUBSTR(M1.Sold_to_Country_Name,INSTR(M1.Sold_to_Country_Name,' ')))),' ',',') AS SC,
T1.Country_Cd

FROM T1

FULL OUTER JOIN M1
ON T1.Sales_org_cd = M1.Sales_org_code
AND (

 (M1.Sold_to_Country_Code IS NULL AND T1.Country_cd ?? (not sure for condition #1)

 (M1.Sold_to_Country_Code IS NOT NULL AND M1.Sold_to_Country_Code NOT LIKE 'Ex%' AND T1.Country_cd=M1.Sold_to_Country_Code )

OR (T1.Country_cd IS NOT NULL AND M1.Sold_to_Country_Code LIKE 'Ex%' AND T1.Country_cd NOT IN (OREPLACE(TRIM(BOTH FROM (SUBSTR(M1.Sold_to_Country_Name,INSTR(M1.Sold_to_Country_Name,' ')))),' ',','))  )

 )

WHERE T1.sales_org_cd IN ('0001','0002')

希望我的解释清楚。 不确定是否可以实现。 感谢您是否可以提供任何意见或建议。

我想出了条件#1的一种方法:使用TO_NUMBER函数将T1.Country_cd中的所有值转换为NULL,然后使用COALESCE将NULL转换为0,并对M1.Sold_to_Country_Code将null转换为0进行类似操作。因此,将条件3的@Fred解决方案汇总在一起,完整的查询应如下所示:

SELECT DISTINCT
T1.sales_org_cd,
M1.Reporting_Country,
M1.Sold_to_Country_Code,
T1.Country_Cd

FROM T1

LEFT OUTER JOIN M1
ON T1.Sales_org_cd = M1.Sales_org_code
AND (

 (M1.Sold_to_Country_Code IS NULL AND COALESCE(TO_NUMBER(T1.Country_cd),'0')=COALESCE(M1.Sold_to_Country_Code,'0') )
OR

 (M1.Sold_to_Country_Code IS NOT NULL AND M1.Sold_to_Country_Code NOT LIKE 'Ex%' AND T1.Country_cd=M1.Sold_to_Country_Code )

OR 
(T1.Country_cd IS NOT NULL AND M1.Sold_to_Country_Code LIKE 'Ex%' AND POSITION(' '||T1.Country_cd||' ' IN M1.Sold_to_Country_Name||' ')=0 )
 )

WHERE T1.sales_org_cd IN ('0001','0002')

我刚刚对其进行了测试,它确实可以用于示例查询。 但是,在实际实践中执行查询似乎需要更长的时间。

有谁可以在优化查询中有更好的主意/解决方案? 任何帮助都非常感谢!

再次感谢@Fred!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM