简体   繁体   中英

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. So I have a transaction table (T1) and another country mapping table (M1) to join together.

In the transaction table (T1), there are also including (for tables joins): (i). SalesOrg Code; (ii). Sold-To Country Code

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

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). If Sold-To Country Code is null, then pull all transactions from T1 in the sales org code (eg. #0001);
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;
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.

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').

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. 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.

(
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.

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:

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!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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