I have to update a column in Table 'A' with values from Table 'B'. If any value in Table 'B'
is null or empty then I have to get the value from table 'C'.
Manu
Use:
UPDATE A
SET column = (SELECT COALESCE(b.val, c.value)
FROM B b
JOIN C c ON c.col = b.col)
COALESCE will return the first non-null value from the list of columns, processing from left to right.
What's odd is you haven't provided how tables B and C relate to one another - if they don't in anyway, you're looking at a cartesian product of the two tables (not ideal). My answer uses a JOIN, in hopes it is possible depending on the data.
Basically:
UPDATE a SET a.FIELD = (CASE WHEN b.FIELD IS NULL or b.FIELD = '' THEN c.FIELD ELSE b.FIELD END)
FROM TABLEA a
LEFT JOIN TABLEB b on a.id = b.someid
LEFT JOIN TABLEC c on a.id = c.someid
Joins may or may not be LEFT, depending on your data, and you may want to handle the case where both b.field and c.field are null.
Related
Looking to use different column values on return after a join, if a value is NOT NULL.
Seems hard to explain but if I have a select statement that names a colum with AS, then Join another valuem and if that is NOT NULL use that new column value in place of the first.
SELECT a.value1 AS value
FROM table a
LEFT JOIN table2 b ON a.id = b.id (assume this is one to one)
What I want is table2 has a column value2, and if that is NOT NULL then make b.value2 AS value
In code would be
if (b.value) {
$value = b.value2;
} else {
$value = a.value1;
}
Use coalesce():
SELECT coalesce(t2.value2, a.value1) AS value
FROM table a LEFT JOIN
table2 b
ON a.id = b.id ;
SELECT
CASE
WHEN b.value2 IS NOT NULL THEN b.value2
ELSE a.value1
END
AS value
FROM table a
LEFT JOIN table2 b ON a.id = b.id
I am trying to update the column (REPT_IND) from table A to the value in table B where A.ID = B.ID and some conditions in table B.
There are some duplicates in table B, but nonetheless the REPT_IND is the same and I still need the value.
How can I do this on Oracle? Any tips are appreciated thank you!
The Following code has the Error:
ORA-01427: single-row subquery returns more than one row
Code:
UPDATE A
SET REPT_IND= (
SELECT B.REPT_IND
FROM B
INNER JOIN A
ON B.ID = A.ID
where A.ID = B.ID
and B.job_type = 'P'
and B.FT_PT is not null
);
You can try also merge statement:
merge into a
using (
select a.id,max(b.rept_ind) rept_ind
from a left join b on a.id=b.id
where b.job_type = 'p'
and b.ft_pt is not null
) b
on (a.id=b.id)
when matched then update
set a.rept_ind=b.rept_ind;
Or if you do not want to set a.rept_ind to null if there is no relevant rows in b:
merge into a
using (
select b.id, max(b.rept_ind) rept_ind
from b
where
b.job_type = 'p'
and b.ft_pt is not null
group by b.id
) b
on (a.id=b.id)
when matched then update
set a.rept_ind=b.rept_ind;
Consider:
update a
set rept_ind= (
select max(b.rept_ind)
from b
where
a.id = b.id
and b.job_type = 'p'
and b.ft_pt is not null
);
There is no need to join table a again in the subquery - a correlation clause is enough. And you can work around possible duplicates by turning on aggregation, which guarantees that only one row will be returned.
You could also use select distinct instead of select max(...) in the subquery. This is somehow more accurate since it does ensure that the multiple rows have the same rept_ind (it they do not, then you would still get the ORA-01427 error).
Just use a correlated subquery . . . and do not repeat the table reference in the subquery:
UPDATE A
SET REPT_IND = (SELECT B.REPT_IND
FROM B
WHERE B.ID = A.ID AND
B.job_type = 'P' AND
B.FT_PT is not null AND
rownum = 1
);
I have two tables... A master ID table and a results ID table with only a few IDs from the master table. I'm looking to create the following SQL Query:
Select
A.ID
(Case when B.ID is in A.ID 1 Else 0 End) as is_found
From
master_table as A
LEFT JOIN results_table as B
ON A.ID = B.ID
The resulting table should have all IDs from master table with a boolean column saying if the ID was found in the results table. Thank you for your help!!
I would use case . . . exists:
Select mt.id,
(case when exists (select 1 from results_table rt where rt.id = mt.id) then 1 else 0 end) as is_found
From master_table ;
First, consider the case where results_table will have either zero or one matching row; in this case, the LEFT JOIN will always give one row for each ID, and B.ID will be NULL if there is no corresponding row in results_table.
We can therefore use a simple CASE to test this:
Select
A.ID,
CASE WHEN B.ID IS NOT NULL THEN 1 ELSE 0 END as is_found
From
master_table as A
LEFT JOIN results_table as B
ON A.ID = B.ID
If there may be more than one row in results_table for the same ID, the LEFT JOIN may in turn create several rows, one for each match.
The result of the CASE statement will be the same for all values of A.ID - if there are zero matches, it will occur once with value 0, and if there are one or more, it will always have the value 1. So we can simply take distinct values of the entire query:
Select Distinct
A.ID,
CASE WHEN B.ID IS NOT NULL THEN 1 ELSE 0 END as is_found
From
master_table as A
LEFT JOIN results_table as B
ON A.ID = B.ID
I have made a query in which 3 tables are used. The first table has all the desired names which I need. The 2nd and 3rd table give me those names on which there is some bill amount. But I need all the names from the 1st table as well.
SELECT a.name,
nvl(c.bill_amount,0)
FROM table_1 a left outer join table_2 b
ON a.name = b.name
left outer join table_3 c on B.phone_number = C.phone_number
AND B.email = C.email
where b.status = 'YES'
and a.VALID = 'Y';
Now, the tables b and c give me limited number of names, lets say 5 on which bill is there. But in table_1, there are 10 names. I want to display them also with 0 bill_amount on their name. I'm using Oracle.
Applying a where clause on the right hand tale basiically makes it an inner join. To keep it OUTER, put the condition in the join conditions
Try:
SELECT a.name,
nvl(c.bill_amount,0)
FROM table_1 a
left outer join table_2 b
ON a.name = b.name
and b.status = 'YES' -- Put it here
left outer join table_3 c
on B.phone_number = C.phone_number
AND B.email = C.email
where a.VALID = 'Y'; -- Only items from the left hand table should go in the where clause
The answer above is right , I would just want to be more precise. The fact is when a left join does not match, the column of the right hand table are set to NULL.
Actually NULL is always propagating value in SQL, so b.status = 'YES' have the value NULL if the join does not math, and then the predicate does not match neither.
The general way to handle this would be (b.status = 'YES' or b.name IS NULL) : because b.name is the join column it is null if and only if join does not match, which may not be the case for b.status.
Because NULL is propagating you cannot use field = NULL but field IS NULL instead.
But it is okay to have it in the join clause when it is more clear.
There are three tables, A,B and C having common columns(name and number)
Table A have 10 records(say x) which can be only from table B(say, y) and table C(say, z) (like, x = y+z).
In table A, there are some records whose value is 0 (zero)
I need to compare those zero value based records using column = name, with other two tables.
And check the column "number" for the same "name" is also zero (0) in table B and table C?
I tried to write the below sample query to test on my small set of 3 tables data- but for some reasons I am not able to get all the 10 records as a result?
SELECT a.name,a.number as A_number, b.number as B_number, c.number as C_number
from A a, B b, C c
WHERE a.name = b.name
The above query gives me data as follows in the sqlfiddle-
http://sqlfiddle.com/#!2/57f86/1
In the above data- theres no record name="hello"
Can anyone please correct me where I am going wrong? and how to get the exact result? I need all the records from Table A. I know if I use left join it will populate all the left table data even if no match.
Possibilities: Table A having records, some may be present in table B
and some in table C, but not on both.
I think this is what you want:
SELECT a.*, b.number as bnumber, c.number as cnumber
from a left outer join
b
on a.name = b.name left outer join
c
on a.name = c.name
where a.number = 0;
By the way, here is a Postgres SQL Fiddle.
It's been over 20 years since the JOIN keyword was added to SQL. Use it:
select
a.name,
a.number as A_number,
b.number as B_number,
c.number as C_number
from A a
left join B b on a.name = b.name
left join C c on a.name = c.name
where a.number = 0
The key here is the use of left join, which allows all rows in table A to be returned, even if there are no matching rows in the other tables.
If you want to just display true/false if the number is zero in the other tables, do this:
select
a.name,
a.number as A_number,
(b.number = 0 and c.number = 0) as zero_elsewhere
from A a
left join B b on a.name = b.name
left join C c on a.name = c.name
where a.number = 0
When you wrote WHERE a.name = b.name, that restricted the records returned from table A to only those that also exist in table B. This is not equivalent to a left join. If you used only a WHERE statement you would need to do:
WHERE ((a.name = b.name) OR (b.name is NULL))
AND
((a.name = c.name) OR (c.name is NULL))
In the comments and other answers, they have been using LEFT JOIN which is easier to write and read. I suggest you adopt that style as it is widely accepted.