简体   繁体   English

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

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

Hi I have a question about table joins in Teradata SQL. 嗨,我对Teradata SQL中的表联接有疑问。 So I have a transaction table (T1) and another country mapping table (M1) to join together. 因此,我有一个交易表(T1)和另一个国家/地区映射表(M1)结合在一起。

In the transaction table (T1), there are also including (for tables joins): (i). 在事务表(T1)中,还包括(对于表联接):(i)。 SalesOrg Code; SalesOrg代码; (ii). (ii)。 Sold-To Country Code 售至国家/地区代码

Table T1: 表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

For the country mapping table (M1), it looks like this: 对于国家/地区映射表(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
.......

What I want to achieve is to join two tables based on below conditions: 我要实现的是根据以下条件联接两个表:

1). 1)。 If Sold-To Country Code is null, then pull all transactions from T1 in the sales org code (eg. #0001); 如果Sold-To Country Code为空,则从销售组织代码中的T1提取所有交易(例如#0001);
2). 2)。 If Sold-To Country Code is NOT NULL and doesn't contains "Ex", then map the transactions from T1 based on SalesOrg Code and Sold-To Country Code; 如果Sold-To国家/地区代码为NOT NULL并且不包含“ Ex”,则根据SalesOrg代码和Sold-To国家/地区代码映射来自T1的交易;
3). 3)。 If Sold-To Country Code contains "Ex" (which means excluding), then map the T1 transactions from the same SalesOrg code but excluding the country codes specified in the last column, as example above: NOT:FR IE IT. 如果“售至”国家/地区代码包含“ Ex”(表示排除),则使用相同的SalesOrg代码映射T1交易,但不包括最后一列中指定的国家/地区代码,例如上面的示例:NOT:FR IE IT。

For #3 condition, I eventually want to convert the values in the string text NOT: FR IE IT into a list so it can be used in the JOIN as like NOT IN ('FR','IE','IT'). 对于#3条件,我最终希望将字符串文本NOT:FR IE IT中的值转换为列表,以便可以像NOT IN('FR','IE','IT')一样在JOIN中使用它。

Ultimately I want to get the results like below (additional column at last - Reporting Country): 最终,我想获得如下结果(最后一列-报告国):

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

........ ........

Any better idea? 有更好的主意吗?

I tried to use STRTOK_SPLIT_TO_TABLE to convert the values FR IE IT into rows and it did work to create such list. 我尝试使用STRTOK_SPLIT_TO_TABLE将FR IE IT值转换为行,并且确实可以创建此类列表。 However, this is not unique case, and there are same situations for other countries, hence, I need the join conditions to be based on each row of the record from M1 table. 但是,这不是唯一的情况,其他国家/地区也存在相同的情况,因此,我需要联接条件基于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  ) 

I have tried below, but it can't be mapped correctly as it will be duplicated mapping for Netherlands with Sold-To country code IE FR IT as well. 我在下面尝试过,但是无法正确映射,因为它将与荷兰的国家代码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')

Hope my explanation is clear. 希望我的解释清楚。 Not sure if those are achievable. 不确定是否可以实现。 Appreciate if you could provide any inputs or suggestion. 感谢您是否可以提供任何意见或建议。

I figured out a way for the condition #1: to convert all values in T1.Country_cd into NULL by using TO_NUMBER function, and then convert NULL into 0 by using COALESCE, and do the similar thing for M1.Sold_to_Country_Code converting null to 0. So taking together the solution from @Fred for condition #3, the full query should be like this: 我想出了条件#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')

I just tested it and it did work for sample querying. 我刚刚对其进行了测试,它确实可以用于示例查询。 However, it seems to take longer time in executing the query in real practice. 但是,在实际实践中执行查询似乎需要更长的时间。

Anyone who can have any better idea/solutions in optimising the query? 有谁可以在优化查询中有更好的主意/解决方案? Any help is really appreciated! 任何帮助都非常感谢!

Thank you @Fred again! 再次感谢@Fred!

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

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