update table from another table using like clause in oracle - sql

i am new to stackoverflow. Am stuck with this problem for weeks but am unable to find similar examples to this (correct me if i am wrong). What i am trying to achieve is updating the values of one table from another table but using a look alike keywords eg. I have 2 tables
table1 (id, item) values:
id | item
-------------
10 | book
20 | copy
30 | pen
table2 (id,item) values:
id | item
-------------
null | the big book
null | the copy machine
null | penpal
Now I want to:
Update table2 A
Set id = Select id From table1 B
Where A.item Like B.item;
My desired outcome is:-
id | item
-------------
10 | the big book
20 | the copy machine
30 | penpal
How do it do it? Thank you all.

update table2 set id =
(select min(id) from table1
where table2.item like '%' || table1.item ||'%' );

Merge :
MERGE INTO Table2 tar
USING
(
SELECT MIN(T1.ID) AS ID, T2.item AS item
Table2 T2
LEFT JOIN
Table1 T1
ON (T2.item LIKE '%'||T1.item||'%')
GROUP BY T2.item
) src
ON (tar.item = src.item)
WHEN MATCHED THEN UPDATE
SET tar.id = src.id;
This solution may be faster.

update table2 t2
set id = ( select min(id) from table1 t1 where item like '%' || t1.item || '%')
where exists ( select 1 from table1 t1 where item like '%' || t1.item || '%');

Related

Find values where related must have list of values

I'm trying to find a simple solution for my SQL Server problem.
I have two tables look like this:
table1
--id
-- data
table2
--id
--table1_id
--value
I have some records like this:
Table1
+-----------------------+
| id | data |
+-----------------------+
| 1 | ? |
+-----------------------+
| 2 | ? |
+-----------------------+
Table2
+-----------------------+
|id | table1_id | value |
+-----------------------+
| 1 | 1 | 'a' |
+-----------------------+
| 2 | 1 | 'b' |
+-----------------------+
| 3 | 2 | 'a' |
+-----------------------+
Now I want to get table1 with all it's additional values where the relation to table2 has 'a' AND 'b' as values.
So I would get the id 1 of table1.
Currently I have an query like this:
SELECT t1.[id], t1.[data]
FROM [table1] t1,
(SELECT [id]
FROM [table1] t1
JOIN [table2] t2 ON t1.[id] = t2.[table1_id] AND t2.[Value] IN('a', 'b')
GROUP BY t1[id]
HAVING COUNT(t2.[Value]) = 2) x
WHERE t1.id = x.id
Has anyone an idea on how to achieve my goal in a simpler way?
One way uses exists:
select t1.*
from table1 t1
where exists (select 1
from table2 t2
where t2.table1_id = t1.id and t2.value = 'a'
) and
exists (select 1
from table2 t2
where t2.table1_id = t1.id and t2.value = 'b'
);
This can take advantage of an index on table2(table1_id, value).
You could also write:
select t1.*
from table1 t1
where (select count(distinct t2.value)
from table2 t2
where t2.table1_id = t1.id and t2.value in ('a', 'b')
) = 2 ;
This would probably also have very good performance with the index, if table2 doesn't have duplicates.
SELECT T1.[id], T1.[data]
FROM table1 AS T1
JOIN table2 AS T2
ON T1.[id]=T2.[table1_id]
JOIN table2 AS T3
ON T1.[id]=T3.[table1_id]
WHERE
T2.[Value] ='a'
AND T3.[Value] = 'b'
As Gordon Linoff suggested, exists clause usage works as well and could be performance efficient depending on the data you are playing with.
you have to do several steps to solve the problem:
established which records are related to table 1 and table 2 and which of these are of value (A or B) and eliminate the repeated ones with the group by(InfoRelationate )
validate that only those related to a and b were allowed by means of a count in the table above (ValidateAYB)
see what data meets the condition of table1 and table 2 and joined table 1
this query meets the conditions
with InfoRelationate as
(
select Table2.table1_id,value
from Table2 inner join
Table1 on Table2.table1_id=Table1.id and Table2.value IN('a', 'b')
group by Table2.table1_id,value
),
ValidateAYB as
(
select InfoRelationate.table1_id
from InfoRelationate
group by InfoRelationate.table1_id
having count (1)=2
)
select InfoRelationate.table1_id,InfoRelationate.value
from InfoRelationate
inner join ValidateAYB on InfoRelationate.table1_id=ValidateAYB.table1_id
union all
select id,data
from Table1
Example code

ORACLE : Update query using two table with has relation

I need to update the column data based on matching record found in both Table.
I want to update the record of NAME column from TABLE2
Following are the tables
Table1
---------------
Id | Name | color
1 | abc | red
2 | def | green
3 | ghi | blue
Table2
---------------
Id | Name | color |fiedId
1 | abc | red | 1
2 | def | green | 1
3 | ghi | blue | 2
Here table1 ID column is the Foreign Key in table2 as fieldId.
So, I want to update all the record which fall under this condition
table1.id = table2.fieldId
Yet another option, using MERGE:
merge into table2 t2
using (select id, name from table1) x
on (t2.fieldid = x.id)
when matched then update set
t2.name = x.name;
Or, for setting the name to 'xxx':
merge into table2 t2
using (select id from table1) x
on (t2.fiedid = x.id)
when matched then update set
t2.name = 'xxx';
Sounds like you just want an update like this:
update table2 t2
set t2.name =
( select t1.name
from table1 t1
where t1.id = t2.fieldid )
Regarding the followup question:
what if i want to set Name = "xxx" for all matching rows?
update table2 t2
set t2.name = 'xxx'
where t2.fieldid in
( select t1.id from table1 t1 )
or this can be written as:
update table2 t2
set t2.name = 'xxx'
where exists
( select null from table1 t1
where t1.id = t2.fieldid )

Get column name from one table by id in another table

I have 2 tables
Table 1:
Query_code | Item_code | Column_Name
2 | 1 | CN1
2 | 2 | CN2
2 | 3 | CN3
Table 2:
Query_code | Source_item| dest_item | pair_code
2 | 1 | 2 | 1
2 | 2 | 3 | 2
What i want to achive is to get source_item-dest_item as result.
According to data that will be:
CN1-CN2
CN2-CN3
What i tried is:
SELECT A.Column_Name
FROM TABLE1 A inner join
TABLE2 B
ON A.QUERY_CODE=B.QUERY_CODE
But this is not even close to my goal
What you need to do is use TABLE2 to identify the source_item and dest_item, then join with TABLE1 the first time to replace source_item with the column name, and join again with TABLE1 to replace dest_item with the other column name.
SELECT A.Column_Name, B.Column_Name
FROM t2 C
LEFT JOIN t1 A
ON C.Source_item=A.Item_code
LEFT JOIN t1 B
ON C.Dest_item=B.Item_code
WHERE C.Query_code=A.Query_code
AND C.Query_code=B.Query_code
Running Example on SQLFiddle
This should work. It is unclear what your Query_Code is meant to do, so I omitted it from the query.
EDIT Inserted Query_code condition as well.
SELECT
Source.Column_Name || '-' || Dest.Column_Name AS ResultPair
FROM
TABLE2 B
INNER JOIN TABLE1 Source
ON B.source_item = Source.item_code AND B.Query_code = Source.Query_code
INNER JOIN TABLE1 Dest
ON B.dest_item = Dest.item_code AND B.Query_code = Dest.Query_code;
Here you go
WITH table1 (query_code, item_code ,column_name ) AS
(SELECT 2,1,'cn1' UNION ALL
SELECT 2,2,'cn2' UNION ALL
SELECT 2,3,'cn3'),
table2 (query_code , source_item, dest_item , pair_code) AS
(SELECT 2,1,2,1 UNION ALL
SELECT 2,2,3,2)
SELECT a.column_name || '-' || c.column_name
FROM table1 a
INNER JOIN table2 b ON a.item_code=b.source_item
INNER JOIN table1 c ON c.item_code=b.dest_item;

Update multiple rows using select statements

Let's say I have these tables and values:
Table1
------------------------
ID | Value
------------------------
2 | asdf
4 | fdsa
5 | aaaa
Table2
------------------------
ID | Value
------------------------
2 | bbbb
4 | bbbb
5 | bbbb
I want to update all the values in Table2 using the values in Table1 with their respective ID's.
I know I can run this:
UPDATE Table2
SET Value = t1.Value
FROM Table2 t2
INNER JOIN Table1 t1 on t1.ID = t2.ID
But what can I do if Table1 and Table2 are actually select statements with criteria? How can I modify the SQL statement to take that into consideration?
This is how such update queries are generally done in Oracle. Oracle doesn't have an UPDATE FROM option:
UPDATE table2 t2
SET t2.value = ( SELECT t1.value FROM table1 t1
WHERE t1.ID = t2.ID )
WHERE EXISTS ( SELECT 1 FROM table1 t1
WHERE t1.ID = t2.ID );
The WHERE EXISTS clause will make sure that only the rows with a corresponding row in table1 are updated (otherwise every row in table2 will be updated; those without corresponding rows in table1 will be updated to NULL).

SQL how to simulate an xor?

I'm wondering if anybody can help me solve this question I got at a job interview. Let's say I have two tables like:
table1 table2
------------ -------------
id | name id | name
------------ -------------
1 | alpha 1 | alpha
3 | charlie 3 | charlie
4 | delta 5 | echo
8 | hotel 7 | golf
9 | india
The question was to write a SQL query that would return all the rows that are in either table1 or table2 but not both, i.e.:
result
------------
id | name
------------
4 | delta
5 | echo
7 | golf
8 | hotel
9 | india
I thought I could do something like a full outer join:
SELECT table1.*, table2.*
FROM table1 FULL OUTER JOIN table2
ON table1.id=table2.id
WHERE table1.id IS NULL or table2.id IS NULL
but that gives me a syntax error on SQL Fiddle (I don't think it supports the FULL OUTER JOIN syntax). Other than that, I can't even figure out a way to just concatenate the rows of the two tables, let alone filtering out rows that appear in both. Can somebody enlighten me and tell me how to do this? Thanks.
Well, you could use UNION instead of OUTER JOIN.
SELECT * FROM table1 t1
LEFT JOIN table2 t2 ON t1.id = t2.id
UNION
SELECT * FROM table1 t1
RIGHT JOIN table2 t2 ON t1.id = t2.id
Here's a little trick I know: not equals is the same as XOR, so you could have your WHERE clause something like this:
WHERE ( table1.id IS NULL ) != ( table2.id IS NULL )
select id,name--,COUNT(*)
from(
select id,name from table1
union all
select id,name from table2
) x
group by id,name
having COUNT(*)=1
I'm sure there are lots of solutions, but the first thing that comes to mind for me is to union all the two tables, then group by name, filter with a having clause on the count.
(
SELECT * FROM TABLE1
EXCEPT
SELECT * FROM TABLE2
)
UNION ALL
(
SELECT * FROM TABLE2
EXCEPT
SELECT * FROM TABLE1
)
This should work on most database servers
SELECT id, name
FROM table1
WHERE NOT EXISTS(SELECT NULL FROM table2 WHERE table1.id = table2.id AND table1.name = table2.name)
UNION ALL
SELECT id, name
FROM table2
WHERE NOT EXISTS(SELECT NULL FROM table1 WHERE table1.id = table2.id AND table1.name = table2.name)