Reputation: 18379
I have 3 tables A
, B
, C
Schema of all 3 tables is same as mentioned below:
id, time1, place, xyz, abc, pqrs
Now both tables A
and B
have many records ( around 10 million)
Now some of the records in A and B are with same id
and some are with different Id
Now I want to merge the records from A
, and B
into Table C
. Merge logic is as follows
1)If records with id = someId is present only in A or B ( only in one table)
then insert record from that table (A/B depending of where its present) in table C
2)If records with id =someId is present in both A and B {
if(A.time1 > B.time2){
insert record from A into C
}else{
insert record from B into C
}
}
I want to do it using a single SQL query , by using outer join between A
and B
. But I am not very clear how to go about it.
Upvotes: 0
Views: 2593
Reputation: 763
Assuming table C
is empty, then something like this would do the trick
INSERT INTO C
SELECT A.*
FROM A LEFT OUTER JOIN B
ON A.ID = B.ID
WHERE (A.TIME1 > B.TIME1 OR B.TIME1 IS NULL)
UNION
SELECT B.*
FROM B LEFT OUTER JOIN A
ON B.ID = A.ID
WHERE (A.TIME1 <= B.TIME1 OR A.ID IS NULL)
Upvotes: 2
Reputation: 5050
Using UNION
, you can try something like this :
INSERT INTO C
SELECT A.*
FROM A
LEFT OUTER JOIN B ON A.ID = B.ID
WHERE A.TIME1 > B.TIME1 OR B.ID IS NULL
UNION
SELECT B.*
FROM B
LEFT OUTER JOIN A ON B.ID = A.ID
WHERE B.TIME1 > A.TIME1 OR A.ID IS NULL
SQLFIDDLE : http://www.sqlfiddle.com/#!4/5019b/2/0
Upvotes: 1
Reputation: 2182
CREATE TABLE t_c
(
id_c NUMBER
, time_c DATE
);
INSERT
WHEN id_a IS NULL THEN INTO t_c(id_c, time_c) VALUES (id_b, time_b)
WHEN id_b IS NULL THEN INTO t_c(id_c, time_c) VALUES (id_a, time_a)
WHEN id_a = id_b AND time_a > time_b THEN INTO t_c(id_c, time_c) VALUES (id_a, time_a)
WHEN id_a = id_b AND time_a <= time_b THEN INTO t_c(id_c, time_c) VALUES (id_b, time_b)
SELECT *
FROM
(
SELECT 1 id_a, DATE'2013-01-01' time_a FROM dual UNION ALL
SELECT 2 id_a, DATE'2013-01-02' time_a FROM dual UNION ALL
SELECT 3 id_a, DATE'2013-01-03' time_a FROM dual UNION ALL
SELECT 4 id_a, DATE'2013-01-04' time_a FROM dual UNION ALL
SELECT 7 id_a, DATE'2013-01-07' time_a FROM dual UNION ALL
SELECT 8 id_a, DATE'2013-01-08' time_a FROM dual
) t_a
FULL JOIN
(
SELECT 1 id_b, DATE'2013-01-01' time_b FROM dual UNION ALL
SELECT 2 id_b, DATE'2013-01-02' time_b FROM dual UNION ALL
SELECT 5 id_b, DATE'2013-01-05' time_b FROM dual UNION ALL
SELECT 6 id_b, DATE'2013-01-06' time_b FROM dual UNION ALL
SELECT 7 id_a, DATE'2013-01-09' time_a FROM dual UNION ALL
SELECT 8 id_a, DATE'2013-01-01' time_a FROM dual
) t_b
ON t_a.id_a = t_b.id_b
;
/*
1 2013-01-01 00:00:00 1 2013-01-01 00:00:00
2 2013-01-02 00:00:00 2 2013-01-02 00:00:00
5 2013-01-05 00:00:00
6 2013-01-06 00:00:00
7 2013-01-07 00:00:00 7 2013-01-09 00:00:00
8 2013-01-08 00:00:00 8 2013-01-01 00:00:00
4 2013-01-04 00:00:00
3 2013-01-03 00:00:00
*/
SELECT *
FROM t_c;
/*
5 2013-01-05 00:00:00
6 2013-01-06 00:00:00
4 2013-01-04 00:00:00
3 2013-01-03 00:00:00
8 2013-01-08 00:00:00
1 2013-01-01 00:00:00
2 2013-01-02 00:00:00
7 2013-01-09 00:00:00
*/
Upvotes: 0
Reputation: 17238
combine 3 result sets:
1., 2. can be combined into 1 left join, 3. is a right join filtered for unique id occurrence. choose a as data source for 2., b for 3., and a/b depending on precedence for 1.; the selection logic can be compacted to a single condition as the time1
comparisons will only yield a boolean if none is null, ie. on record from 1.
insert
into c ( id, time1, place, xyz, abc, pqrs )
(
select id1
, time1
, place
, xyz
, abc
, pqrs
from (
select a1.id id1
, b1.id id2
, CASE b1.time1 > a1.time1 then b1.time1 else a1.time1 end time1
, CASE b1.time1 > a1.time1 then b1.place else a1.place end place
, CASE b1.time1 > a1.time1 then b1.xyz else a1.xyz end xyz
, CASE b1.time1 > a1.time1 then b1.abc else a1.abc end abc
, CASE b1.time1 > a1.time1 then b1.pqrs else a1.pqrs end pqrs
from a a1
left join b b1 on ( b1.id = a1.id )
union
select b2.id id1
, a2.id id2
, b2.time1
, b2.xyz
, b2.place
, b2.abc
, b2.pqrs ,
from b b2
left join a a2 on ( a2.id = b2.id )
where a2.id is null
) pairs
)
;
Upvotes: 0
Reputation: 14209
In a single request:
insert into C
-- Outer join on B: if B is null null or A has greater time take A
select case when B.id is null or A.time1 > B.time1 then A.id else B.id end,
case when B.id is null or A.time1 > B.time1 then A.time1 else B.time1 end,
case when B.id is null or A.time1 > B.time1 then A.place else B.place end,
case when B.id is null or A.time1 > B.time1 then A.xyz else B.xyz end,
case when B.id is null or A.time1 > B.time1 then A.abc else B.abc end,
case when B.id is null or A.time1 > B.time1 then A.pqrs else B.pqrs end
from A, B
where B.id (+) = A.id
union all
-- Then get the ones in B and not in A with outer join on A
select B.id, B.time1, B.place, B.xyz, B.abc, B.pqrs
from B, A
where A.id (+) = B.id
and A.is is null
Upvotes: 0