Оператор SQL для согласования с различными операторами - PullRequest
0 голосов
/ 26 января 2012

Это очень связано с вопросом: Оператор SQL для согласования , но с большим поворотом.

С учетом приведенной ниже схемы:

create table TBL1 (ID varchar2(100) primary key not null, MATCH_CRITERIA timestamp);
create table TBL2 (ID varchar2(100) primary key not null, MATCH_CRITERIA timestamp);
create table TBL_RESULT (ID varchar2(100) primary key not null, TBL1_ID varchar2(100), TBL2_ID varchar2(100));

create unique index UK_TBL_RESULT_TBL1_ID on TBL_RESULT(TBL1_ID);
create unique index UK_TBL_RESULT_TBL2_ID on TBL_RESULT(TBL2_ID);

insert into TBL1 VALUES('1', to_date('01/26/2012 20:00:00', 'mm/dd/yyyy hh24:mi:ss'));
insert into TBL1 VALUES('2', to_date('01/26/2012 20:05:00', 'mm/dd/yyyy hh24:mi:ss'));

insert into TBL2 VALUES('3', to_date('01/26/2012 19:59:00', 'mm/dd/yyyy hh24:mi:ss'));
insert into TBL2 VALUES('4', to_date('01/26/2012 20:04:00', 'mm/dd/yyyy hh24:mi:ss'));

Наш текущий запрос:

INSERT INTO TBL_RESULT (ID, TBL1_ID, TBL2_ID) 
SELECT rawtohex(sys_guid()),t1.id,t2.id 
FROM
(SELECT t1.match_criteria,t1.id, row_number() OVER (PARTITION BY t1.match_criteria ORDER BY t1.id) rn 
FROM tbl1 t1) t1,  
(SELECT t2.match_criteria,t2.id, row_number() OVER (PARTITION BY t2.match_criteria ORDER BY t2.id) rn 
FROM tbl2 t2) t2
WHERE t1.match_criteria between t2.match_criteria - (10/1440) AND t2.match_criteria + (10/1440)
AND t1.rn=t2.rn

Вывод:

| ID  |  TBL1_ID | TBL2_ID |
| '1' |  '1'     |    '3'  |
| '2' |  '1'     |    '4'  |
| '3' |  '2'     |    '3'  |
| '4' |  '2'     |    '4'  |

Как видите, результаты не соответствуютуникальное ограничение (дубликат TBL1_ID / дубликат TBL2_ID).Это связано с тем, что:

  1. RN для каждой записи всегда равно 1 (следовательно, всегда равно)
  2. Дата между двумя записями составляет 10 минут.

Мы ожидаем вывод, похожий на приведенную ниже таблицу:

| ID  |  TBL1_ID | TBL2_ID |
| '1' |  '1'     |    '4'  |
| '2' |  '2'     |    '3'  |

Примечание 1: не имеет значения, совпадает ли «1» с «3», но затем2 'должно совпадать с' 4 ', чтобы соответствовать ограничениям, если T1.MATCH_CRITERIA находится в пределах 10 минут от T2.MATCH_CRITERIA.

Примечание 2: мы вставляем миллион записей из TBL1 и другоймиллион записей из TBL2.Таким образом, последовательная вставка с использованием PL / SQL недопустима, если она не может выполняться очень быстро (менее 15 минут).

Примечание 3: несоответствующие данные должны быть удалены.Ожидаются и несбалансированные данные.

Примечание 4: мы не ограничены только выполнением 1 запроса.Подойдет серия конечных запросов.

Ответы [ 2 ]

1 голос
/ 26 января 2012

Я думаю, что это может работать:

INSERT INTO TBL_RESULT (ID, TBL1_ID, TBL2_ID)
select seq_tbl_result.nextval,
tt1.id, tt2.id
from (select id, v, row_number() over(partition by v order by id) rn
from (select distinct t1.id,
case
when (t1.match_criteria between
t2.match_criteria - (10 / 1440) and
t2.match_criteria + (10 / 1440)) then
1
else
2
end v
from tbl1 t1, tbl2 t2
where t1.match_criteria between
t2.match_criteria - (10 / 1440) and
t2.match_criteria + (10 / 1440))) tt1,
(select id, v, row_number() over(partition by v order by id) rn
from (select distinct t2.id,
case
when (t1.match_criteria between
t2.match_criteria - (10 / 1440) and
t2.match_criteria + (10 / 1440)) then
1
else
2
end v
from tbl1 t1, tbl2 t2
where t1.match_criteria between
t2.match_criteria - (10 / 1440) and
t2.match_criteria + (10 / 1440))) tt2
where tt1.v = tt2.v
and tt1.rn = tt2.rn
1 голос
/ 26 января 2012

В данный момент ваш запрос производит перекрестное соединение, потому что ваши бизнес-правила не предоставляют механизм для связывания одной записи в T1 с одной записью в T2. Учитывая, что это явно игрушечный пример, нам трудно предложить что-то, кроме чего-то очень упрощенного:

(SELECT t1.match_criteria,t1.id, row_number() OVER (ORDER BY t1.match_criteria,t1.id) rn 
.... 
(SELECT t2.match_criteria,t2.id, row_number() OVER (ORDER BY t2.match_criteria,t2.id) rn 

Это будет просто сопоставлять первую строку в наборе результатов T1 с первой строкой в ​​наборе результатов T2, второй строкой в ​​наборе результатов T1 со второй строкой в ​​наборе результатов T2 и так далее.

SQL> INSERT INTO TBL_RESULT (ID, TBL1_ID, TBL2_ID) 
SELECT seq_tbl_result.nextval,t1.id,t2.id 
FROM
(SELECT t1.match_criteria,t1.id, row_number() OVER (ORDER BY t1.match_criteria, t1.id) rn 
FROM tbl1 t1) t1,  
(SELECT t2.match_criteria,t2.id, row_number() OVER (ORDER BY t2.match_criteria, t2.id) rn 
FROM tbl2 t2) t2
WHERE t1.match_criteria between t2.match_criteria - (10/1440) AND t2.match_criteria + (10/1440)
AND t1.rn=t2.rn
SQL> SQL> SQL>   2    3    4    5    6    7    8    9  
 10  /

2 rows created.


SQL> select * from tbl_result
  2  /

ID     TBL1_I TBL2_I
------ ------ ------
9      1      3
10     2      4

SQL> 

Это, вероятно, не то, что вы хотите. В этом случае вам нужно объяснить свои данные и правила для решения, какие связи с чем. Например, есть ли какая-то модель для любого набора времени, которая позволила бы вам получить опорную точку?


Кроме того, когда я буду править миром, будут расстреливаться люди, которые используют столбцы VARCHAR2 (100) для хранения числовых идентификаторов.

...