2013-08-16 3 views
0

У меня есть 3 таблицы A, B, Cприсоединяемых записей из двух таблиц в третьей, используя SQL

Схема всех 3-х таблиц так же, как указано ниже:

id, time1, place, xyz, abc, pqrs 

Теперь обе таблицы A и B имеют много записей (около 10 миллионов)

Теперь некоторые из записей в A и B с такими же id, а некоторые с разными Id

Теперь я хочу объединить записи с A и B в таблицу C. Объединить логика заключается в следующем

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 
      } 
    } 

Я хочу сделать это с помощью одного запроса SQL, с помощью внешнего соединения между A и B. Но я не очень понимаю, как это сделать.

+1

вы что-нибудь пробовали? –

+0

Я думаю, что вы имели в виду столбцы, а не схемы –

ответ

2

Предполагая, что таблица C пусто, то что-то, как это будет делать трюк

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) 
+0

hmmm .. для того, кто проголосовал за него. ОК, если вам не понравился мой ответ ... но вы могли бы рассказать мне, что именно вам не понравилось? Если у меня возникла проблема с моим решением, сообщите мне –

+0

: Спасибо, что ответили. Но это решение только заботится о случаях, когда обе таблицы A и B имеют соответствующий идентификатор. Что в случае, если записи существуют в A, а не в B (или наоборот). Нам также нужно вставить такие данные в C. Как можно мы позаботимся об этом? – user93796

+0

@ user93796 он обрабатывает другие записи (существует в A, но не в B и наоборот), поэтому его «левое внешнее соединение» и «объединение». Левое внешнее соединение получило бы все записи в A, а не в B и A, со временем больше/позже B времени, то же самое со вторым запросом.И «union» будет объединять записи –

0

объединить 3 результирующие наборы:

  1. записей с общими идентификаторами.
  2. записи с идентификаторами только присутствуют в
  3. записей с идентификаторами только присутствующих в б

1., 2. могут быть объединены в 1 слева присоединиться, 3. имеет право присоединиться фильтруется для уникального идентификатора возникновения , выберите источник данных для 2., b для 3. и a/b в зависимости от приоритета для 1; логика выбора может быть уплотнена до одного условия, так как сравнения time1 приведут только к логическому, если ни один не равен нулю, т.е. на записи с 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 
     ) 
     ; 
0

В одном запросе:

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 
0
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 
*/ 
1

Использование UNION, вы можете попробовать что-то вроде этого:

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