How to write an SQL query that uses wild-card map to do transformation

ⅰ亾dé卋堺 提交于 2019-12-13 04:47:13

问题


I have a source table A with a number of columns. I want to do a transformation of the source table to a target table. I would like to have a mapping table with same columns as the source table A and with rows that make up the translations.

Here is an example of the table A:

COL1    COL2    COL3
aktie   ja         2
aktie   nej        3
obli    ja         2

and here is the mapping table

COL1    COL2    COL3        TRANSFORM
aktie   ja      NULL            3
aktie   NULL    NULL            4

Now, the idea is to join the source table with the mapping and get the transformed value returned. The use of NULL should serve as a wildcard. So my desired result should be that the first row in table A would match the first row in the mapping table and return the value 3

For the second row - and here is my challenge - I want it to match the second row in the mapping table because it is NOT matched by rows that have a value already (which would result in the transformed value 3) and as the second mapping row has NULL in column two, it should be treated as a wildcard (although taking into account other rows in the mapping table as well).

My first attempt would be something like

select A.*, m.res
from tab1 A
inner join mapping m on t.col1 = isnull(m.col1, t.col1) 
                     and t.col2 = isnull(m.col2, t.col2)
and ...

but the problem is that the isnull(..,..) will match everything and not only return matches except the listed possible values that would result in a different transformation.

I am looking for a generic solution that would Work for any table with any number of columns, not only this particular table-layout mentioned here.

I have been thinking a lot about this and cannot really seem to come up with the solution, so please help :)


回答1:


Here is one way to do this using a CTE (will work on SQL Server and Oracle)

WITH Map3 as 
( -- TRANSFORM WILL BE NULL IF A MATCH WAS NOT MADE
   SELECT T1.COL1, T1.COL2, T1.COL3, M.TRANSFORM
   FROM Table1 T1
   LEFT JOIN Mapping M ON T1.COL1 = M.COL1 
                      AND T1.COL2 = M.COL2
                      AND T1.COL3 = COALESCE(M.COL3, T1.COL3)
), Map2 as
(
   SELECT T1.COL1, T1.COL2, T1.COL3, COALESCE(T1.TRANSFORM,M.TRANSFORM)
   FROM Map3 T1
   LEFT JOIN Mapping M ON T1.COL1 = M.COL1 
                      AND T1.COL2 = COALESCE(M.COL2, T1.COL2)
                      AND T1.TRANSFORM IS NULL
)
SELECT * 
FROM Map2

I believe it is clear how this works and how to "extend" this to more columns.


If you can't use a CTE this is functionally the same and can be nested as far as you like:

SELECT T1.COL1, T1.COL2, T1.COL3, COALESCE(T1.TRANSFORM,M.TRANSFORM)
FROM (
   -- TRANSFORM WILL BE NULL IF A MATCH WAS NOT MADE
   SELECT T1.COL1, T1.COL2, T1.COL3, M.TRANSFORM
   FROM Table1 T1
   LEFT JOIN Mapping M ON T1.COL1 = M.COL1 
                      AND T1.COL2 = M.COL2
                      AND T1.COL3 = COALESCE(M.COL3, T1.COL3)
) T1
LEFT JOIN Mapping M ON T1.COL1 = M.COL1 
                   AND T1.COL2 = COALESCE(M.COL2, T1.COL2)
                   AND T1.TRANSFORM IS NULL


来源:https://stackoverflow.com/questions/30199573/how-to-write-an-sql-query-that-uses-wild-card-map-to-do-transformation

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!