Your instruction
LEFT JOIN {SOURCE} ON INPUT.{KEY} = {SOURCE}.{KEY}
implicates that existing tables that you want to join have the same columns as INPUT TABLE - KEY_1 and/or KEY_2.
I created two such tables ET_1 and ET_2:
Select * From ET_1;
FLD_1 FLD_2 KEY_1 KEY_2
-------------------- -------------------- -------------------- --------------------
ABC DEF G H
Select * From ET_2;
COL_1 COL_2 KEY_2
-------------------- -------------------- --------------------
PQR STU D
... INPUT_TBL and CONF_TBL for testing purposes...
Select * From INPUT_TBL;
KEY_1 KEY_2
-------------------- --------------------
A B
C D
E F
G H
I J
K L
Select * From CONF_TBL;
SOURCE FIELD KEY LABEL
-------------------- -------------------- -------------------- --------------------
ET_1 FLD_1 KEY_1 LBL_1
ET_1 FLD_2 KEY_2 LBL_2
ET_2 COL_1 KEY_2 LBL_3
ET_2 COL_2 KEY_2 LBL_4
The sql code that you asked for could be generated dynamicaly using PL/SQL:
SET SERVEROUTPUT ON
Declare
CURSOR c IS Select "SOURCE", "FIELD", "KEY", "LABEL" From CONF_TBL;
mSource VarChar2(20);
mField VarChar2(20);
mKey VarChar2(20);
mLabel VarChar2(20);
mSQL_sel VarChar2(1000) := 'Select i.*, ';
mSQL_from VarChar2(1000) := 'From INPUT_TBL i ';
mSQL_join VarChar2(1000);
mSQL VarChar2(4000);
cnt Number := 0;
ta VarChar2(32);
Begin
OPEN c;
LOOP
Fetch c Into mSource, mField, mKey, mLabel;
Exit When c%NOTFOUND;
cnt := cnt + 1;
ta := 'ta' || cnt;
mSQL_sel := mSQL_sel || ta || '.' || mField || ' "' || Nvl(mLabel, ta || '_' || mField) || '", ';
mSQL_join := mSQL_join || 'LEFT JOIN ' || mSource || ' ' || ta || ' ON(' || ta || '.' || mKey || ' = i.' || mKey || ')' || Chr(10);
END LOOP;
CLOSE c;
mSQL_sel := SubStr(mSQL_sel, 1, Length(mSQL_sel) -2);
mSQL_join := SubStr(mSQL_join, 1, Length(mSQL_join) -1);
mSQL := mSQL_sel || Chr(10) || mSQL_from || Chr(10) || mSQL_join;
DBMS_OUTPUT.PUT_LINE(mSQL);
End;
/
Resulting (mSQL) code could then be used as regular sql or as refcursor or anything else .... Below is generated code and result against the tables described above
Select i.*, ta1.FLD_1 "LBL_1", ta2.FLD_2 "LBL_2", ta3.COL_1 "LBL_3", ta4.COL_2 "LBL_4"
From INPUT_TBL i
LEFT JOIN ET_1 ta1 ON(ta1.KEY_1 = i.KEY_1)
LEFT JOIN ET_1 ta2 ON(ta2.KEY_2 = i.KEY_2)
LEFT JOIN ET_2 ta3 ON(ta3.KEY_2 = i.KEY_2)
LEFT JOIN ET_2 ta4 ON(ta4.KEY_2 = i.KEY_2)
PL/SQL procedure successfully completed.
KEY_1 KEY_2 LBL_1 LBL_2 LBL_3 LBL_4
-------------------- -------------------- -------------------- -------------------- -------------------- --------------------
C D PQR STU
A B
G H ABC DEF
E F
K L
I J
6 rows selected.
If there are no labels defined (optional) in table CONF_TBL then the result would be like here:
Select i.*, ta1.FLD_1 "ta1_FLD_1", ta2.FLD_2 "ta2_FLD_2", ta3.COL_1 "ta3_COL_1", ta4.COL_2 "ta4_COL_2"
From INPUT_TBL i
LEFT JOIN ET_1 ta1 ON(ta1.KEY_1 = i.KEY_1)
LEFT JOIN ET_1 ta2 ON(ta2.KEY_2 = i.KEY_2)
LEFT JOIN ET_2 ta3 ON(ta3.KEY_2 = i.KEY_2)
LEFT JOIN ET_2 ta4 ON(ta4.KEY_2 = i.KEY_2)
PL/SQL procedure successfully completed.
KEY_1 KEY_2 ta1_FLD_1 ta2_FLD_2 ta3_COL_1 ta4_COL_2
-------------------- -------------------- -------------------- -------------------- -------------------- --------------------
C D PQR STU
A B
G H ABC DEF
E F
K L
I J
6 rows selected.
U P D A T E
If you want to avoid possible duplication of the same joins you could change the cursor to generate the fields (of duplicated joins) in the same row.
CURSOR c IS
Select "SOURCE", "FIELD" as FIELD_1,
CASE WHEN CNT = 2 THEN 'xxx'
WHEN LEAD(CNT, 1) OVER(Order By "SOURCE", "KEY", "FIELD") = 2
THEN LEAD("FIELD", 1) OVER(Order By "SOURCE", "KEY", "FIELD")
END as FIELD_2,
"KEY", "LABEL"
From ( Select "SOURCE", "FIELD", "KEY", "LABEL",
Count("FIELD") OVER(Partition By "SOURCE", "KEY" Order By "FIELD") "CNT"
From CONF_TBL
Order By "SOURCE", "KEY", "FIELD" );
--
-- Cursor result
SOURCE FIELD_1 FIELD_2 KEY LABEL
-------------------- -------------------- -------------------- -------------------- --------------------
ET_1 FLD_1 KEY_1
ET_1 FLD_2 KEY_2
ET_2 COL_1 COL_2 KEY_2
ET_2 COL_2 xxx KEY_2
Next you should adjust the code to handle two fields...
SET SERVEROUTPUT ON
Declare
CURSOR c IS
Select "SOURCE", "FIELD" as FIELD_1,
CASE WHEN CNT = 2 THEN 'xxx'
WHEN LEAD(CNT, 1) OVER(Order By "SOURCE", "KEY", "FIELD") = 2
THEN LEAD("FIELD", 1) OVER(Order By "SOURCE", "KEY", "FIELD")
END as FIELD_2,
"KEY", "LABEL"
From ( Select "SOURCE", "FIELD", "KEY", "LABEL",
Count("FIELD") OVER(Partition By "SOURCE", "KEY" Order By "FIELD") "CNT"
From CONF_TBL
Order By "SOURCE", "KEY", "FIELD" );
mSource VarChar2(20);
mField_1 VarChar2(20);
mField_2 VarChar2(20);
mKey VarChar2(20);
mLabel VarChar2(20);
mSQL_sel VarChar2(1000) := 'Select i.*, ';
mSQL_from VarChar2(1000) := 'From INPUT_TBL i ';
mSQL_join VarChar2(1000);
mSQL VarChar2(4000);
cnt Number := 0;
ta VarChar2(32);
Begin
OPEN c;
LOOP
Fetch c Into mSource, mField_1, mField_2, mKey, mLabel;
Exit When c%NOTFOUND;
If mField_2 = 'xxx' Then
GoTo NextRow;
End If;
cnt := cnt + 1;
ta := 'ta' || cnt;
--
mSQL_sel := mSQL_sel || ta || '.' || mField_1 || ' "' || Nvl(mLabel, ta || '_' || mField_1) || '", ';
If mField_2 Is Not Null And mField_2 != 'xxx' Then
mSQL_sel := mSQL_sel || ta || '.' || mField_2 || ' "' || Nvl(mLabel, ta || '_' || mField_2) || '_A' || '", ';
End If;
If mField_2 Is Null OR mField_2 != 'xxx' Then
mSQL_join := mSQL_join || 'LEFT JOIN ' || mSource || ' ' || ta || ' ON(' || ta || '.' || mKey || ' = i.' || mKey || ')' || Chr(10);
End If;
<<NextRow>>
Null;
END LOOP;
CLOSE c;
mSQL_sel := SubStr(mSQL_sel, 1, Length(mSQL_sel) -2);
mSQL_join := SubStr(mSQL_join, 1, Length(mSQL_join) -1);
mSQL := mSQL_sel || Chr(10) || mSQL_from || Chr(10) || mSQL_join;
DBMS_OUTPUT.PUT_LINE(mSQL);
End;
/
SQL command and it's result is:
Select i.*, ta1.FLD_1 "ta1_FLD_1", ta2.FLD_2 "ta2_FLD_2", ta3.COL_1 "ta3_COL_1", ta3.COL_2 "ta3_COL_2_A"
From INPUT_TBL i
LEFT JOIN ET_1 ta1 ON(ta1.KEY_1 = i.KEY_1)
LEFT JOIN ET_1 ta2 ON(ta2.KEY_2 = i.KEY_2)
LEFT JOIN ET_2 ta3 ON(ta3.KEY_2 = i.KEY_2)
PL/SQL procedure successfully completed.
KEY_1 KEY_2 ta1_FLD_1 ta2_FLD_2 ta3_COL_1 ta3_COL_2_A
-------------------- -------------------- -------------------- -------------------- -------------------- --------------------
C D PQR STU
A B
G H ABC DEF
E F
K L
I J
6 rows selected.