2015-05-12 21 views
0

我有一個包含許多列的源表A.我想要將源錶轉換爲目標表。我想要有一個與源表A相同列的映射表,以及構成翻譯的行。如何編寫使用通配符映射進行轉換的SQL查詢

下面是表A的例子:

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

,這裏是映射表現在

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

,這個想法是加入源表的映射,並得到轉化返回值。使用NULL應該用作通配符。所以我希望的結果應該是表A中的第一行將匹配映射表中的第一行並返回值3對於第二行 - 這裏是我的挑戰 - 我希望它匹配第二行在映射表中,因爲它不與已具有值的行匹配(這會導致轉換的值爲3),並且由於第二個映射行在第二列中具有NULL,因此應該將其視爲通配符(儘管考慮到映射表中的其他行也是如此)。

我第一次嘗試將像

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(..,..)會匹配一切,不僅返回匹配的不同之處在於將導致不同的轉換所列出的可能值。

我正在尋找一種通用的解決方案,可以用於任何數量的列的任何表格,而不僅僅是這裏提到的這個特定的表格佈局。

我一直在想了很多關於這一點,並不能真正似乎拿出解決方案,所以請幫助:)

+0

哪個平臺您使用?對於我的想法,最好是SQL Server,Oracle或DB2(不適用於mysql) – Hogan

+0

最好是,它既可以在SQL服務器上運行,也可以在Oracle上運行,如果你的想法只適用於其中的一種,SQL服務器是首選的 – codermanden

+0

我並不關注你認爲你看到的問題:「問題是,isnull(..,..)將匹配所有內容。」如果'm.col1'爲空,則'isnull(m.col1,t.col1)'(或'coalesce(m.col1,t.col1)')將返回't.col1',否則返回'm.col1'。這怎麼會導致不同的行爲,而不是將null當作通配符來做呢? –

回答

0

這裏是要做到這一點使用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 

我相信很清楚這是如何工作的以及如何「擴展」到更多列。


如果您不能使用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 
+0

嗨Hogan,它適用於我給出的示例,但我希望它能夠一般工作。如果我將映射表中的第二行更改爲 NULL NULL 2 我希望它匹配源表的第三行。在你的例子中,col1沒有合併。我試圖在col1上應用coalesce,但這不起作用,那麼這意味着我將不得不爲N列編寫Map2,Map3,... ManN以使其工作?那麼對於具有許多列和行的表,這將如何執行? – codermanden

+0

@codermaden是的,你需要1-n個子查詢....想不到更好的方法來做到這一點。 – Hogan

+0

垃圾。那麼,那正是我想要避免的,但是如果你得出同樣的結論 - 而且沒有其他人提出更好的解決方案 - 我想這是唯一的方法。幸運的是,它可以生成,所以現在我只是想知道對於有100,000行和50列的源表有多高效......我想壓力測試會告訴:)感謝您的幫助,霍根! – codermanden

相關問題