Oracle Compare 2 equijoined tables - oracle

The concept is that i am trying to compare 2 equijoined tables to see if the whether the other query has the same values or if they exist in the other query.
The way i join the tables is:
"select a.sth, a.sth2, a.st3, b.value for table1 a, table2 b where a.key = b.valkey"
This will result in displaying the values columns of table1 and next the column value2 from table2 where their key is the same.
Now i have another 2 tables which contain similar data and i want to check if the results of my query exists in the query i will build for the other tables like:
"select a.sth, a.sth2, a.st3, b.value for table3 a, table4 b where a.key = b.valkey"
The only way i thought of doing this was with nested implicit cursors. Like for example:
BEGIN
FOR item IN (select a.sth, a.sth2, a.st3, b.value for table1 a, table2 b where a.key = b.valkey)
LOOP
Begin
FOR item2 IN (select a.sth, a.sth2, a.st3, b.value for table3 a, table4 b where a.key = b.valkey)
LOOP
Begin
if (item1.sth = item2.sth) and (item1.sth2 = item2.sth2) and (item1.sth3 = item2.sth3) and (item1.value = item2.value) Then
dbms_output.put_line("Found and value is the same");
Elsif (item1.sth = item2.sth) and (item1.sth2 = item2.sth2) and (item1.sth3 = item2.sth3) and Not (item1.value = item2.value) Then
dbms_output.put_line("Found but value is different");
Exception When no_data_found then
dbms_output.put_line("item1 was not found in table3");
End;
END LOOP;
End;
END LOOP;
END;
The above is just pseudo code of what i thought to do. Can i do something like this or is there an alternative that has better performance which i can use? I am looking forward to your suggestions.

You don't need cursors for this. In general, set-based code is going to work better. The query would look something like this:
select coalesce(a.key, b.valkey) as thekey,
a.sth, a.sth2, a.st3, b.value
(case when a.key is null then 'Not found in a'
when b.key is null then 'Not found in b'
when (a.sth = b.sth) and (a.sth2 = b.sth2) and (a.sth3 = b.sth3) and
(a.value = b.value)
then 'Found and same'
when (a.sth = b.sth) and (a.sth2 = b.sth2) and (a.sth3 = b.sth3) and
(a.value <> b.value)
then 'Found and different'
else 'Other!!!'
end)
from table1 a full outer join
table2 b
on a.key = b.valkey

Related

SQL Update with Join and Sub Query

I have the following queries and have trouble putting them together:
DECLARE #Value1 INT = 3
DECLARE #Value2 INT = 6
UPDATE TableA SET
Column1 = B.NewValue,
FROM TableA A INNER JOIN TableB B ON A.NumberId = B.NumberId AND
AND A.Type = #Value1
UPDATE TableA SET
Column2 = B.NewValue,
FROM TableA A INNER JOIN TableB B ON A.NumberId = B.NumberId AND
AND A.Type = #Value2
My goal is to have one query with a join that updates the columns depending on the values in the join.
This I just an example (in my case there are more columns and therefore more queries) but overall I want to have as few queries as possible (in this example: one query instead of two)
DECLARE #Value1 INT = 3
DECLARE #Value2 INT = 6
UPDATE TableA SET
Column1 = B.NewValue, --if the join joins on #Value1
Column2 = B.NewValue, --if the join joins on #Value2
FROM TableA A INNER JOIN TableB B ON A.NumberId = B.NumberId AND
AND A.Type = B.#Value1/#Value2
Is this possible (using a sub query for example)?
You can try using CASE EXPRESSION
UPDATE TableA SET
Column1 = CASE WHEN A.Type = #Value1 THEN B.NewValue
ELSE A.Column1 END,
Column2 = CASE WHEN A.Type = #Value2 THEN B.NewValue
ELSE A.Column2 END
FROM TableA A INNER JOIN TableB B ON A.NumberId = B.NumberId AND
AND A.Type IN (#Value1, #Value2)

Update statement with concat & inner join on Oracle

I'm trying to create an update query that concatenates 3 fields from a table to 1 field in another table
The first table called table1
ID DESC
12 left:Middle:Right
The second table Table 2
ID FLD1 FLD2 FLD3
12 left Middle Right
Trying to update all the desc field on Table1 with the values of table2 where table1.id = table2.id
update table1 A SET A.DESC = (SELECT CONCAT(B.fld1, ':', B.fld2, ':', B.fld3)
from table2 B
where A.ID = B.ID)
Where A.id = 12;
However, I'm getting an error from the above query saying "invalid number of arguments" Any idea what am I doing wrong? or how can I get this done in a better way?
CONCAT accepts only two parameters, which means that you have to use nested CONCATs.
Though, you'd rather use the double pipe || operator which doesn't have such a restriction. So:
update table1 A SET A.DESC = (SELECT B.fld1 ||':'|| B.fld2 ||':'|| B.fld3 --> this
from table2 B
where A.ID = B.ID)
Where A.id = 12;
To update all matching rows, you could
update table1 A SET A.DESC = (SELECT B.fld1 ||':'|| B.fld2 ||':'|| B.fld3 --> this
from table2 B
where A.ID = B.ID)
Where exists (select null
from table2 b
where a.id = b.id);
or MERGE:
merge into table1 a
using table2 b
on (b.id = a.id)
when matched then update set a.desc = b.fld1 ||':'|| b.fld2 ||':'|| b.fld3;
As you got duplicates, DISTINCT might help, e.g.
update table1 a set
a.desc = (select distinct b.fld1 ||':'|| b.fld2 ||':'|| b.fld3
from table2 b
where a.id = b.id
)
where exists ...
If not, then you'll have to see what to do with these duplicates. If possible, use yet another column(s) in WHERE clause. Or, if you don't really care which concatenated combination fits, use aggregate function(s) such as MIN or MAX, e.g.
update table1 a set
a.desc = (select max(b.fld1 ||':'|| b.fld2 ||':'|| b.fld3)
from table2 b
where a.id = b.id
)
where exists ...

How to join hive tables based on condition of the joining column

We have a hive table like below:
num value
123 A
456 B
789 C
101 D
The joining table is:
num Symbols
123 ASC
456001 JEN
456002 JEN
456003 JEN
789001 CON
101 URB
Our expected result:
num value symbols
123 A ASC
456 B JEN
789 C CON
101 D URB
Currently we are joining the tables twice in order to get the results.
Like first time insert into some tmp table using the below query:
select
a.num,
a.value,
b.symbols
from mytable a
join mytable b on a.num = b.num;
This query is producing the results for keys 123,101.
Next, we are running another query like below:
select
a.num,
a.value,
b.symbols
from mytable a
join mytable b on CONCAT(a.num,'001') = b.num;
This query is producing the results for keys 456, 789.
These two queries results are inserted into some tmp hive table and we select the final results from the tmp table.
This looks a bad design overall. but I would like to know if there is a better way to achieve this. Thanks.
Query Result
for
Select
a.num
,a.value
,b.symbols
from
(select substr(num,3) as num, value from table)a
join
(select substr(num,3) as num, symbols from table) b
on a.num = b.num
a.num a.value b.symbols
3 A ASC
1 D URB
OK, just one sql can implement your requirement.see below, table a is the table with value column and table b is the table with the symbols column, the SQL:
select
distinct a.num,
a.value,
b.symbols
from
mytable1 a
join
mytable2 b on substr(cast(b.num as string),0,3) = cast(a.num as string)
If datatype of num is String then you can try with Substr
Select
a.num
,a.value
,b.symbols
from a join b on
substr(a.num,3) = substr(b.num,3)
Can you pls try this
Select
a.num
,a.value
,b.symbols
from
(select substr(num,3) as num, value from table)a
join
(select substr(num,3) as num, symbols from table) b
on a.num = b.num
Can you try with left semi join with above query as shown below.
Select
a.num,
a.value,
b.symbols
from
mytable1 a
Left semi join
mytable2 b on substr(cast(b.num as string),0,3) = cast(a.num as string)

Statement update with inner join on Oracle Error

I have a query which works fine in Sybase, but when I run it on Oracle I get the following error
update table1
set chk = b.chkakhir
from table1 a
inner join (select substr('0'||inkdwil,-2) wil,substr(chk,-4) site, wil||site chkakhir,wil||'0' chkdcust from table2) b
on a.chk = b.site
where length(a.chk) = 4;
update table1
set chk = b.chkakhir
from table1 a
inner join (select right('0'||inkdwil,2) wil,right(chk,4) site, wil||site chkakhir,wil||'0' chkdcust from table2) b
on a.chk = b.site
where len(a.chk) = 4;
query work in oracle
Wrong syntax, as far as Oracle is concerned. Should look like this:
UPDATE table1
SET chk =
(SELECT b.chkakhir --> instead of FROM, you have to use SELECT here
FROM table1 a
INNER JOIN (SELECT SUBSTR ('0' || inkdwil, -2) wil,
SUBSTR (chk, -4) site,
wil || site chkakhir,
wil || '0' chkdcust
FROM table2) b
ON a.chk = b.site
WHERE LENGTH (a.chk) = 4);
query work in oracle
update table1
set chk = (select chk
from table1 a
inner join (select substr('0'||inkdwil,-2) wil,substr(chk,-4) site, substr('0'||inkdwil,-2)||substr(chk,-4) chkakhir,substr('0'||inkdwil,-2)||'0' chkdcust from table2) b
on a.chk = b.site)
where length(a.chk) = 4;

Use a value of a query in a subquery

I'm trying to make a query that have a lot of subquerys (4 subquerys), but for the subquerys I need to take a value of the query, can anyone help me? This is the query:
SELECT DISTINCT tab1.value1,
ISNULL((SELECT SUM(tab2.quantity) FROM tab2 INNER JOIN tab3 ON tab2.id_tab2 = tab3.id_tab2 INNER JOIN tab4 ON tab3.id_tab3 = tab4.id_tab3 WHERE tab4.value = "value1"), 0) AS v1,
ISNULL((SELECT SUM(tab2.quantity) FROM tab2 INNER JOIN tab3 ON tab2.id_tab2 = tab3.id_tab2 INNER JOIN tab4 ON tab3.id_tab3 = tab4.id_tab3 WHERE tab4.value = "value2"), 0) AS v2
What I need to do is that in the subquerys, make an INNER JOIN with that value1 the subquery make the adding but just with the values that are of the value1, because right now the subquery make the add of all the values located in the table that are equal with "value1" or "value2", I have tryed to make a subquery like these:
ISNULL((SELECT SUM(tab2.quantity) FROM tab2 INNER JOIN tab3 ON tab2.id_tab2 = tab3.id_tab2 INNER JOIN tab4 ON tab3.id_tab3 = tab4.id_tab3 INNER JOIN tab5 ON tab2.id_tab5 = tab5.id_tab5 INNER JOIN tab1 ON tab5.id_tab1 = tab1.id_tab1 INNER JOIN tab1 ON tab1.value1 = tab1.value1 WHERE tab4.value = "value1"), 0) AS v1
But obviously it didn't function, I also have tried to use an allias for the value1 but it says that it doesn't exist, anyone have an idea?
Im going to take a stab at it... It looks like you are trying to join the four tables by _id and aggregate a sum based on the child table's (tab4) value.
In the below example I used three tables, but the idea is the same. If this doesnt meet your needs perhaps you can repurpose this example to clearly define your requirements:
declare #tab1 table (i int primary key, value varchar(10));
insert into #tab1
select 1, 'one' union all select 2, 'two'
declare #tab2 table (i int primary key, quantity varchar(10));
insert into #tab2
select 1, 10 union all
select 2, 20
declare #tab3 table (i int primary key, value varchar(10));
insert into #tab3
select 1, 'value1' union all
select 2, 'value2'
select t1.value,
sum(case when t3.value = 'value1' then t2.quantity else 0 end),
sum(case when t3.value = 'value2' then t2.quantity else 0 end)
from #tab1 t1
join #tab2 t2 on t1.i = t2.i
join #tab3 t3 on t2.i = t3.i
group
by t1.value;

Resources