SQL Update with Join and Sub Query - performance

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)

Related

Getting ORA-00918: column ambiguously defined error on 10g but works in 11g

select distinct p.id,
format_name(p.fname, p.lname,'local000000000000001') full_name,
p.username,
p.person_no,
jobinfo.name,
company.name2,
company.name,
dom.name,
per_mgr.username,
a.name
from cmt_person p
inner join fgt_locale loc on loc.id='local000000000000001'
left outer join tpt_company company on p.company_id = company.id
left outer join tpt_ext_job_type jobinfo on p.jobtype_id = jobinfo.id AND jobinfo.locale_id=loc.id
inner join fgt_domain dom on p.split = dom.id
left outer join fgt_gen gen on gen.id1 = p.id and gen.TYPE = 301 and gen.str2 IS NULL
left outer join fgt_ext_admin_managed_lov a on a.id = gen.id2 and a.locale_id = loc.id
left outer join cmt_person per_mgr on per_mgr.id = p.manager_id
inner join fgt_address a on a.owner_id = p.id
where ( p.terminated_on is null or p.terminated_on >= sysdate)
and( (p.type = 100 and p.split in ('domin000000000000007','domin000000000001107','domin000000000001108','domin000000000001109','domin000000000001104','domin000000000001103','domin000000000001106','domin000000000001105','domin000000000000001','domin000000000001102','domin000000000001110'))
or (p.type = 200 and p.split in ('domin000000000000007','domin000000000001107','domin000000000001108','domin000000000001109','domin000000000001104','domin000000000001103','domin000000000001106','domin000000000001105','domin000000000000001','domin000000000001102','domin000000000001110')) )
AND 1=1
AND lower(p.status) = lower('A')
AND lower(a.country) like lower('USA' || '%')
AND p.type in (decode('1','1',100,'2',200,'0',p.type))
AND p.manager_id in ('emplo000000000034578')
ORDER BY 2,3,4,5,6,7,8,9,10
This is the query I have defined table alias for all tables
Do I need column aliases for following columns for 10g?
jobinfo.name ,
company.name2 ,
company.name ,
dom.name
Two tables share the same alias ("a"): fgt_ext_admin_managed_lov and fgt_address. Change it, as that won't work:
SQL> select a.deptno
2 from dept a, emp a;
select a.deptno
*
ERROR at line 1:
ORA-00918: column ambiguously defined
SQL>
Look at below code :-
left outer join fgt_ext_admin_managed_lov a <<<
..
..
inner join fgt_address a <<<<
You have used same alias name for both tables. Change it to any other alias name.

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;

Oracle Compare 2 equijoined tables

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

Inner join in Linq with more than 2 datatables

i have 3 tables
t1==>
t1.ID t1.co1 t1.col2
1 a b
2 a b
t2==>
t2.ID t2.co1 t2.col2
1 a b
2 a b
t3==>
t3.ID t3.co1 t3.col2
1 a b
2 a b
i want inner join between all three tables using Linq and want selected column in 4th datatable.
equivalent sql query:
SELECT t1.ID,t2.col1,t3.col2
FROM t1
INNER JOIN t2 ON t1.ID=t2.ID
INNER JOIN t3 ON t1.ID=t3.ID
t4==>
t1.ID t2.co1 t3.col2
1 a b
2 a b
Something like this
var Result =
from row1 in t1
join row2 in t2 on row1.ID equals row2.ID
join row3 in t3 on row1.ID equals row3.ID
select new { ID = row1.ID, Col1 = row2.col1, Col2 = row3.col2 }
DataTable dt = Result.CopyToDataTable();
Use LoadDataRow() to get a DataTable from an anonymous type as here. Else Result.CopyToDataTable().
//Get the column list as same as table1 to new datatable
DataTable table4 = table1.Clone();
var Result =
from x in t1.AsEnumerable() join
y in t2.AsEnumerable() on x.Field<int>("ID") equals y.Field<int>("ID") join
z in t3.AsEnumerable() on x.Field<int>("ID") equals z.Field<int>("ID")
select new table4.LoadDataRow(
new object[] {
x.ID,
y.col1,
z.col2
}, false);

Join and batch update in LINQ to SQL

Can something like this be written in LINQ to SQL:
UPDATE Table1
SET CustomerName = t2.Name
FROM Table1 t1 JOIN Table2 t2
ON t1.TableID = t2.TableID
var result = from t1 in context.Table1
join t2 in context.Table2 on t1.TableID = t2.TableID
select new {t1, t2};
result.ToList().ForEach(i => i.t1.CustomerName = i.t2.Name);
context.SubmitChanges();

Resources