I have 3 tables A(a1, a2) , B (b1, b2), C (c1, c2). I want to perform update in the following way:
UPDATE A
SET A.a2 = (SELECT 2* SUM(C.c2)
FROM B JOIN C
ON B.b1 = C.c1 WHERE A.a1 = B.b2)
WHERE A.a1 = (SELECT B.b2
FROM B JOIN C
ON B.b1 = C.c1 HAVING SUM(C.c2) > 1000);
The problem with this approach is the tables B and C need to be joined multiple times.
Is there any good solution to solve this problem?
I tried:
UPDATE A SET A.a2 = (SELECT CASE
WHEN SUM(C.c2) > 1000 THEN 2*SUM(C.c2)
ELSE A.a2
END
FROM B JOIN C
ON B.b1 = C.c1
WHERE A.a1 = B.b2);
but it does not use the index on a1 and also it will update all rows in table A which is even slower than the original one
This kind of update is typically faster when done with a MERGE instead:
MERGE INTO a
using
(
SELECT b.b2, 2 * SUM(C.c2) as c2_sum
FROM B
JOIN C ON B.b1 = C.c1
group by b.b2
HAVING SUM(C.c2) > 1000
) t on (t.b2 = a.a1)
when matched then update
set a2 = t.c2_sum;
If its really long operation you may create intermediate table where you calculate result. But you need to have primary key on both tables
Create table int_a as
SELECT 2* SUM(C.c2) as new_a2
, B.b2
FROM B JOIN C
ON B.b1 = C.c1 WHERE A.a1 = B.b2
GROUP BY B.b2
HAVING SUM(C.c2) > 1000
alter table int_a add constraint primary key pk_int_a (b2);
alter table a add constraint primary key pk_a (a2);
and update table a with join
update (select a2, int_a.new_a2
from A, INT_A
where A.a1 = INT_A.b2)
set a2 = new_a2
You can use "with clause"
update A
SET A.a2 =
((with data as (SELECT B.b2, C.c2 FROM B JOIN C ON B.b1 = C.c1)
select *
from data_b_c)
select * from data b_c, A where A.a1 = b_c.b2 HAVING SUM(b_c.c2) > 1000)
Related
I have tables A,B and C. I need to select certain values from all rows in Table A and then for every row in A, I need to update values in Table B and Table C.
Pseudo Code would look like this:
SELECT A1, A2, A3, A4 FROM Table A
UPDATE Table B SET B2=A2, B3=A3, B4=A4 WHERE B1 = A1;
UPDATE Table C SET C2=A2, C3=A3, C4=A4 WHERE C1 = A1;
How can I achieve this?
In Oracle, you would use two update statements:
update b
set (b2, b3, b4) = (select a2, a3, a4 from a where a.a1 = b.b1);
update c
set (c2, c3, c4) = (select a2, a3, a4 from a where a.a1 = c.b1);
You need two update statements. You could use an inline view:
update (
select a.a2, a.a3, a.a4 , b.b2, b.b3, b.b4
from a
inner join b on b.b1 = a.a1
) u
set u.b2 = u.a2, u.b3 = u.a3, u.b4 = u.a4
The upside is that this only updates matching rows - while, using the correlated subquery technique, you need to repeat the subquery in the where clause.
Another neat syntax that does what you want in Oracle is merge:
merge into b
using a on (a.a1 = b.a1)
when matched then update set b.b2 = a.a2, b.b3 = a.a3, b.b4 = a.a4;
Suppose, i have table A with columns a1, a2 and B table with b1, b2.
I need to join them like this
proc sql;
create C as
select a1, b1
from A as t1
left join B( where=(b1=max(select b1 from B)) as t2
on t1.a2 = t2.b2
run;
The problem is in where=(a1=max(select a1 from A)). It doesn't work somewhy. I need a where= solution, because B is big and where= is really fast
Your condition is on the first table. Hence, in a left join, such a condition usually goes in the where clause. Conditions on the second table would go in the on clause.
One method of doing what you want is to use a subquery:
proc sql;
create C as
select a1, b1
from A t1 left join
B t2
on t1.a2 = t2.b2
where t1.a1 = (select max(tt1.a1) from A tt1)
run;
It seems you only got the syntax wrong. This gets you the B record where b2 matches a2 and b1 is the maximum b1 value in the table.
create table c as
select a.a1, b.b1
from a
left join b on b.b2 = a.a2
and b.b1 = (select max(b1) from b);
Or are you simply trying to get the maximum b1 from all B records where b2 matches a2? That would be:
create table c as
select a.a1, max(b.b1)
from a
left join b on b.b2 = a.a2
group by a.a1;
I have a query with 2 tables Table A and Table B.
Table_A : A_ID, B_ID, A3, A4, A5
Table_B : B_ID, B2.
I want value of column A3 from Table_A and B2 from Table_B.
I tried this query:
select
b.B2, a.A3
from
Table_A a
join
Table_B b on (a.A_ID = b.B_ID)
The query returns nothing. What am I doing wrong?
It would seem that the B_ID column in Table A is the foreign key to Table B - in that case, you need to join on that column:
select
b.B2, a.A3
from
Table_A a
inner join
Table_B b on a.B_ID = b.B_ID
Use a.B_ID (not a.A_ID) to establish the join between the two tables.
Im trying to write a query that will return a set of columns from three different tables.
The table that is link between the other two tables is called Table_A, it contains the keys of for the other two tables.
The second table is called the Table_B and the last table is called the Table_C.
Table_A columns.
| a_ID (primary key)| b_ID (foreign key)| c_ID
(foreign key)| ..... |
Table_B columns
|b_ID (primary key)| b1 | b2 | ...... |
Table_C columns
| c_ID (primary key) | c1 | c2 | ...... |
This is my SQL Query below. (Im only concerned with the columns above although there are more in each table.)
SELECT b.b_ID
, b.b1
, b.b2
, a.a_ID
, c.c1
, c.c2
FROM Table_A AS a
JOIN Table_B AS b ON a.b_ID = b.b_ID
JOIN Table_C AS c ON a.c_ID = c.c_ID
Im using open office for my projects and the error I'm getting is
"Table not found in statement [ SELECT b.b_ID
, b.b1
, b.b2
, a.a_ID
, c.c1
, c.c2
FROM Table_A AS a
JOIN Table_B AS b ON a.b_ID = b.b_ID
JOIN Table_C AS c ON a.c_ID = c.c_ID]"
For some reason if I change the select statement just to get all columns (*) it returns the correct results but I need to narrow it down to the columns listed in my query.*
SELECT *
FROM Table_A AS a
JOIN Table_B AS b ON a.b_ID = b.b_ID
JOIN Table_C AS c ON a.c_ID = c.c_ID'
EDIT: I have removed the actual table and column names so that you don't have to understand the story to help with the issue.
Shouldn't your WHERE clause be:
WHERE b.eventStartDate > '2013-10-01'
?
This is a "spot the difference" type of question...
Could someone please verify whether inner join is valid with UPDATE statment in PL SQL?
e.g.
Update table t
set t.value='value'
from tableb b inner join
on t.id=b.id
inner join tablec c on
c.id=b.id
inner join tabled d on
d.id=c.id
where d.key=1
This synthax won't work in Oracle SQL.
In Oracle you can update a join if the tables are "key-preserved", ie:
UPDATE (SELECT a.val_a, b.val_b
FROM table a
JOIN table b ON a.b_pk = b.b_pk)
SET val_a = val_b
Assuming that b_pk is the primary key of b, here the join is updateable because for each row of A there is at most one row from B, therefore the update is deterministic.
In your case since the updated value doesn't depend upon another table you could use a simple update with an EXIST condition, something like this:
UPDATE mytable t
SET t.VALUE = 'value'
WHERE EXISTS
(SELECT NULL
FROM tableb b
INNER JOIN tablec c ON c.id = b.id
INNER JOIN tabled d ON d.id = c.id
WHERE t.id = b.id
AND d.key = 1)
update t T
set T.value = 'value'
where T.id in (select id from t T2, b B, c C, d D
where T2.id=B.id and B.id=C.id and C.id=D.id and D.key=1)
-- t is the table name, T is the variable used to reffer to this table