0

Just general question, can anyone pls help how to perform left join on union data. I have query where I am doing union of data(using table1 and table2) based on few conditions now I need to perform left outer join with third table(table5) ,so I am looking for help how to do it. Just sample query will be fine.

I have created scenario on fiddle where I have done union based on few conditions using table 1 and table 2.https://dbfiddle.uk/WN6uC5MH Now I need to use output of union and perform left join on third table i.e table 5.So I need to do left join on field 6 of table 5 with output field 1 of union data if it matches then insert rows in table 5 all values will remain same except field 9 which we will get from union output data(field3):

Output will look like this :

'j','abc','def','xyz_inc'
'j','abc','def','5_abc'
'j','abc','def','6_abc'
3
  • 2
    You'll just shove that entire SQL into a subquery and perform your left join on that. SELECT * FROM (<big union SELECT here>) as sub LEFT OUTER JOIN table3 ON sub.field1 = table3.field6; Commented Apr 15, 2024 at 19:18
  • @JNevill-Thank you for sharing,actually i know this syntax and have tried but getting error when i am using alias after closure of bracket in the end. Can you pls help in fiddle(dbfiddle.uk/WN6uC5MH ) how to do it using my query? Commented Apr 15, 2024 at 19:57
  • 1
    Since you are already using CTEs, I've re-organized your query and then instead of sticking your union into a subquery wholesale, I just added a new CTE that references the original two. Then at the end of all the CTE defs, we can perform the join: dbfiddle.uk/U-P4vSpW Commented Apr 15, 2024 at 20:22

1 Answer 1

1
  1. You can translate() once instead of calling replace() twice. You can also merge your translate() calls instead of nesting those.
  2. You can regexp_split_to_table() directly instead of wrapping unnest(string_to_array()).
  3. As @JNevill pointed out, all you need to do is nest the query you have, either in a CTE or a subquery, then join to that.

Demo at db<>fiddle:

with your_big_union as (
    select field1,field2,string_agg(distinct fld,',') field3
    from(
        select *
        from(
            select field1,field2,fld
            from table1 t1
            left join (
                select * from table2
                cross join regexp_split_to_table(trim(translate(field4,'{}','')),',') fld
              )t2
              on concat(t1.field2,';') similar to concat('%',t2.field3,'[();]%')
        )x
    )b
      where field2 like '%fn@_%' escape '@' and fld is not null
    group by field1,field2
    union
    (with cte as (
        select field1,field2
              ,''''
               ||translate( btrim(field2)
                            ,E'\n"'''
                            ,'' )
               ||''''  as edited_field2 
      from table1)
    ,cte2 as (
        select *,t.spotted_table as spotted_target,s.spotted_table as spotted_source
        from cte
        left join regexp_matches(
             edited_field2
            ,'(?:UPDATE|INTO)(?:\s+ONLY)?\s+([[:alpha:]_]+[\.\w]*|"[^"]+"(?:\."[^"]+")?)'
            ,'gi'
          ) with ordinality as target_matches(hits,n1) on true
      left join unnest(target_matches.hits) with ordinality as t(spotted_table,n2) on true
      left join   regexp_matches(
             edited_field2
            ,'(?:FROM|JOIN|USING|TABLE)(?:\s+ONLY)?\s+([[:alpha:]_]+[\.\w]*|"[^"]+"(?:\."[^"]+")?)'
            ,'gi'
          ) with ordinality as source_matches(hits,n1) on true
      left join unnest(source_matches.hits) with ordinality as s(spotted_table,n2) on true)
    select field1
          ,string_agg(distinct spotted_target,',') as spotted_targets
         -- ,string_agg(distinct spotted_source,',') as spotted_sources
          ,edited_field2
    from cte2 where edited_field2 not like '%fn@_%' escape '@' and spotted_target is not null
    and coalesce(split_part(spotted_target,'.',1) !~* '_inc"?$',true)
      and coalesce(split_part(spotted_source,'.',1) !~* '_inc"?$',true)
    group by field1,edited_field2
    order by field1))
select * 
from table5 left join your_big_union 
on lower(your_big_union.field1) = table5.field6;
  1. If table5.field6 joins to field1, you'll get no matches because you uppercased your 'J' in field, while field6 holds a lowercase. I'm not sure why you expect 3 results if you only have a single 'j' on both sides of the join.
Sign up to request clarification or add additional context in comments.

12 Comments

Example : dbfiddle.uk/sj8S5lK2 so here I don't need 'INC' table rows.How to filter it out ?
@Ram You can filter those out the exact same way the other query does: !~* '_inc"?$' and its best to do that before aggregating: demo. If you aim to aggregate, then unnest, it might be easier to array_agg(), then unnest() directly - less overhead, more reliable and doesn't force you to sanitise things in case an additional , slips through.
Question - Is there way to compare field 3 with field 9 after union where you are doing select in the end. dbfiddle.uk/MXhCQg5R. basically in below select query: select * from table5 left join your_big_union on lower(your_big_union.field1) = table5.field6; I have tried doing field3!=unnest(string_to_array(field9,',')) but its throwing ERROR: set-returning functions are not allowed in JOIN conditions.
If you used regular array_agg(), it would be a trivial field3<>all(field9) but you can still do field3!=all(string_to_array(field9,',')): demo. In the demo I think it's the field3 that holds the multiple values, and it's the field9 that holds the single one.
@Zegarek-Thank you so much.I have couple of questions, at some places we have comments also starting with ('--','/*')Is there any way that we can skip source and targets for comments as its not required. I know that sql parser will be best for this but just wondering for workaround. Also, Currently in spotted targets we have used regex for INSERT and UPDATE...Is there way to put regex on (Delete from or Delete *from)I have tried keeping INSERT|UPDATE|DELETE like this but its not working as expected.I think might be because FROM clause being used in Spotted sources?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.