如何编写使用通配符映射进行转换的 SQL 查询
How to write an SQL query that uses wild-card map to do transformation
我有一个来源 table A 有很多列。我想将源 table 转换为目标 table。我想要一个映射 table,其列与源 table A 相同,行组成翻译。
这里是 table A:
的例子
COL1 COL2 COL3
aktie ja 2
aktie nej 3
obli ja 2
这是映射 table
COL1 COL2 COL3 TRANSFORM
aktie ja NULL 3
aktie NULL NULL 4
现在,我们的想法是将源 table 与映射连接起来,并获得转换后的值 returned。 NULL 的使用应作为通配符。所以我想要的结果应该是 table A 中的第一行将匹配映射中的第一行 table 和 return 值 3
对于第二行 - 这是我的挑战 - 我希望它匹配映射中的第二行 table 因为它不匹配已经有值的行(这将导致转换值 3) 并且由于第二个映射行在第二列中有 NULL,因此应将其视为通配符(尽管也考虑了映射中的其他行 table)。
我的第一次尝试是这样的
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 ...
但问题是 isnull(..,..)
将匹配所有内容,而不仅仅是 return 匹配,但列出的可能导致不同转换的值除外。
我正在寻找一种通用解决方案,它适用于具有任意数量列的任何 table,而不仅仅是这里提到的这个特定的 table-layout。
我一直在思考这个问题,但似乎无法真正想出解决方案,所以请帮忙:)
这是使用 CTE 执行此操作的一种方法(适用于 SQL Server 和 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
我相信它是如何工作的以及如何"extend"它到更多列。
如果您不能使用 CTE,这在功能上是相同的,并且可以根据需要嵌套:
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
我有一个来源 table A 有很多列。我想将源 table 转换为目标 table。我想要一个映射 table,其列与源 table A 相同,行组成翻译。
这里是 table A:
的例子COL1 COL2 COL3
aktie ja 2
aktie nej 3
obli ja 2
这是映射 table
COL1 COL2 COL3 TRANSFORM
aktie ja NULL 3
aktie NULL NULL 4
现在,我们的想法是将源 table 与映射连接起来,并获得转换后的值 returned。 NULL 的使用应作为通配符。所以我想要的结果应该是 table A 中的第一行将匹配映射中的第一行 table 和 return 值 3
对于第二行 - 这是我的挑战 - 我希望它匹配映射中的第二行 table 因为它不匹配已经有值的行(这将导致转换值 3) 并且由于第二个映射行在第二列中有 NULL,因此应将其视为通配符(尽管也考虑了映射中的其他行 table)。
我的第一次尝试是这样的
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 ...
但问题是 isnull(..,..)
将匹配所有内容,而不仅仅是 return 匹配,但列出的可能导致不同转换的值除外。
我正在寻找一种通用解决方案,它适用于具有任意数量列的任何 table,而不仅仅是这里提到的这个特定的 table-layout。
我一直在思考这个问题,但似乎无法真正想出解决方案,所以请帮忙:)
这是使用 CTE 执行此操作的一种方法(适用于 SQL Server 和 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
我相信它是如何工作的以及如何"extend"它到更多列。
如果您不能使用 CTE,这在功能上是相同的,并且可以根据需要嵌套:
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