Home > database >  Oracle SQL - New row amongst two different id variables with same root variable
Oracle SQL - New row amongst two different id variables with same root variable

Time:07-30

I am trying to combine 4 data sets into one. The tables are linked by a person id and sample id. Two of those tables have a "specific same ID" field where I would like to create a new row for the each value in t4.specificsampleid and leave those blank. Similarly all t3 related columns would be blanks/nulls when t4 is populated. Any help would be greatly appreciated.

t1.ID t1.main_spec t2.ind t3.specificsampleid t4.specificsampleid
10R46 R1005 y R1005AB R1005_st1
10R46 R1005 y R1005CD R1005_TB12
10R46 R1005 y R1005EF R1005_QZ9

IDEAL OUTPUT:

t1.ID t1.main_spec t2.ind t3.specificsampleid t4.specificsampleid
10R46 R1005 y R1005AB
10R46 R1005 y R1005CD
10R46 R1005 y R1005EF
10R46 R1005 y R1005_st1
10R46 R1005 y R1005_TB12
10R46 R1005 y R1005_QZ9

CodePudding user response:

Ideally, you would provide the input table definitions and not just the expected output, but if I'm understanding correctly, I think you might just want to use a UNION ALL.

Something like:

SELECT t1.ID, t1.main_spec, t2.ind, t3.specificsampleid t3ssid, null t4ssid
FROM t1 INNER JOIN t2
  ON [Condition]
 INNER JOIN t3
  ON [Condition]
UNION ALL
SELECT t1.ID, t1.main_spec, t2.ind, null t3ssid, t4.specificsampleid t4ssid
FROM t1 INNER JOIN t2
  ON [Condition]
 INNER JOIN t4
  ON [Condition]

The first part will get all the rows with a match on t3 (and put null in the relevant t4 column), the second part will get all the rows with a match on t4 (and put null in the relevant t3 column), and the UNION ALL will combine them.

In other words, it will get two rows if there is a match in t3 and t4, or one row if there is only a match in one.

If you need rows where there is a match in neither t3 nor t4, you could add a third part after another UNION ALL or edit one of the existing parts to handle that case.

I'm sure there are alternatives, but I hope this is a good starting point for your problem.

CodePudding user response:

The WITH clause is here just for sample data generation and, as such, it is not the part of the answer.

I assume that the first table in your question is a result that you already have (as a view maybe) and that this resulting dataset is starting point to get the expected result.
Using just a union with crossed where conditions

WITH
    tbl AS
        (
            Select '10R46' "T1_ID", 'R1005' "T1_MAIN_SPEC", 'Y' "T2_IND", 'R1005AB' "T3_SPEC_ID", 'R1005_ST1' "T4_SPEC_ID" From Dual Union All
            Select '10R46' "T1_ID", 'R1005' "T1_MAIN_SPEC", 'Y' "T2_IND", 'R1005CD' "T3_SPEC_ID", 'R1005_TB12' "T4_SPEC_ID" From Dual Union All
            Select '10R46' "T1_ID", 'R1005' "T1_MAIN_SPEC", 'Y' "T2_IND", 'R1005EF' "T3_SPEC_ID", 'R1005_QZ9' "T4_SPEC_ID" From Dual
        )
SELECT 
    T1_ID "T1_ID", T1_MAIN_SPEC "T1_MAIN_SPEC", T2_IND "T2_IND", T3_SPEC_ID "T3_SPEC_ID", null "T4_SPEC_ID"
FROM 
    tbl  
WHERE
    T3_SPEC_ID Is Not Null
UNION ALL    
SELECT  
    T1_ID "T1_ID", T1_MAIN_SPEC "T1_MAIN_SPEC", T2_IND "T2_IND", Null "T3_SPEC_ID", T4_SPEC_ID "T4_SPEC_ID"
FROM 
    tbl  
WHERE 
    T4_SPEC_ID Is Not Null
--  
--  R e s u l t
--  
--  T1_ID T1_MAIN_SPEC T2_IND T3_SPEC_ID T4_SPEC_ID
--  ----- ------------ ------ ---------- ----------
--  10R46 R1005        Y      R1005AB               
--  10R46 R1005        Y      R1005CD               
--  10R46 R1005        Y      R1005EF               
--  10R46 R1005        Y                 R1005_ST1  
--  10R46 R1005        Y                 R1005_TB12 
--  10R46 R1005        Y                 R1005_QZ9

Using full outer join and some data transformation - here is the SQL and result.

WITH
    tbl AS
        (
            Select '10R46' "T1_ID", 'R1005' "T1_MAIN_SPEC", 'Y' "T2_IND", 'R1005AB' "T3_SPEC_ID", 'R1005_ST1' "T4_SPEC_ID" From Dual Union All
            Select '10R46' "T1_ID", 'R1005' "T1_MAIN_SPEC", 'Y' "T2_IND", 'R1005CD' "T3_SPEC_ID", 'R1005_TB12' "T4_SPEC_ID" From Dual Union All
            Select '10R46' "T1_ID", 'R1005' "T1_MAIN_SPEC", 'Y' "T2_IND", 'R1005EF' "T3_SPEC_ID", 'R1005_QZ9' "T4_SPEC_ID" From Dual
        )
SELECT DISTINCT
    T1_ID,
    T1_MAIN_SPEC,
    T2_IND,
    CASE WHEN B_T3_SPEC_ID Is Null And B_T4_SPEC_ID Is Null THEN T3_SPEC_ID ELSE Null END "T3_SPEC_ID",
    CASE 
        WHEN CASE WHEN B_T3_SPEC_ID Is Null And B_T4_SPEC_ID Is Null THEN T3_SPEC_ID ELSE Null END Is Null 
        THEN T4_SPEC_ID 
    ELSE Null
    END "T4_SPEC_ID"
FROM
    (
        SELECT 
             a.T1_ID, a.T1_MAIN_SPEC, a.T2_IND, 
             a.T3_SPEC_ID, 
             a.T4_SPEC_ID,
             CASE WHEN a.T4_SPEC_ID = b.T4_SPEC_ID THEN b.T3_SPEC_ID ELSE Null END "B_T3_SPEC_ID", 
             CASE WHEN a.T3_SPEC_ID <> b.T3_SPEC_ID THEN Null ELSE b.T4_SPEC_ID END "B_T4_SPEC_ID"
        FROM
            tbl a
        FULL OUTER JOIN
            tbl b ON (b.T1_ID = a.T1_ID And b.T1_MAIN_SPEC = a.T1_MAIN_SPEC And b.T2_IND = a.T2_IND)
    )
ORDER BY
    T1_ID,
    T1_MAIN_SPEC,
    T2_IND
--  
--  R e s u l t
--  
--  T1_ID T1_MAIN_SPEC T2_IND T3_SPEC_ID T4_SPEC_ID
--  ----- ------------ ------ ---------- ----------
--  10R46 R1005        Y      R1005AB               
--  10R46 R1005        Y      R1005CD               
--  10R46 R1005        Y      R1005EF               
--  10R46 R1005        Y                 R1005_QZ9  
--  10R46 R1005        Y                 R1005_ST1  
--  10R46 R1005        Y                 R1005_TB12                         

Regards...

  • Related