Дополнительные «Критерии» в предложении ON внутреннего соединения - PullRequest
1 голос
/ 14 июня 2011

Как правильно (внутренне) соединить две таблицы, когда On-Clause-Criteria зависит от одного из двух столбцов? Поэтому Table1 должен присоединиться, когда один из двух столбцов равен одному столбцу Table2.

Взгляните на следующий упрощенный T-SQL, чтобы понять, что я имею в виду и правильно ли я это сделал:

SET TRANSACTION ISOLATION LEVEL READ COMMITTED
GO
BEGIN TRANSACTION;
GO
create table #RMA1(
    SSN_IN varchar(15),
    SSN_OUT varchar(15)
)
create table #RMA2(
    SSN_NUMBER varchar(15),
)
INSERT INTO #RMA1 VALUES('012590001827977', '351600035840752');
INSERT INTO #RMA1 VALUES('332653577440220', '351600035804105');
INSERT INTO #RMA1 VALUES('350302031074780', '350302031074780');
INSERT INTO #RMA1 VALUES('351649036778024', '351806033440194');

INSERT INTO #RMA2 VALUES('012590001827977');
INSERT INTO #RMA2 VALUES('332653577440220');
INSERT INTO #RMA2 VALUES('350302031074780');
INSERT INTO #RMA2 VALUES('351649036778024');
INSERT INTO #RMA2 VALUES('351600035840752');
INSERT INTO #RMA2 VALUES('351600035804106');

SELECT SSN_IN,SSN_OUT,SSN_NUMBER FROM #RMA1 INNER JOIN
#RMA2 ON (#RMA1.SSN_IN = #RMA2.SSN_NUMBER OR
          #RMA1.SSN_Out = #RMA2.SSN_NUMBER)

DROP TABLE #RMA1;
DROP TABLE #RMA2;
GO
COMMIT TRANSACTION;
GO

Результат:

SSN_IN          SSN_OUT            SSN_NUMBER
012590001827977 351600035840752    012590001827977
012590001827977 351600035840752    351600035840752
332653577440220 351600035804105    332653577440220
350302031074780 350302031074780    350302031074780
351649036778024 351806033440194    351649036778024

Q: Так правильно ли объединять таблицы с OR в ON -Клазе внутреннего соединения?

Он правильно возвращает 5 записей и удаляет последнюю запись # RM2, потому что она не находится ни в #RM1.SSN_IN, ни в #RM1.SSN_OUT. Но мне плохо, что это не всегда дает правильный результат. На самом деле производительность реального полного запроса очень низкая.

1 Ответ

3 голосов
/ 14 июня 2011

Результат должен быть правильным, но вы правильно поняли, что производительность плохая.База данных не может эффективно использовать индексы, так как она должна сканировать индекс и выполнять арифметическую операцию для каждого элемента.

Вместо этого два левых объединения позволят базе данных лучше использовать индексы:

select
  SSN_IN,
  SSN_OUT,
  coalesce(T1.SSN_NUMBER, T2.SSN_NUMBER) as SSN_NUMBER
from
  #RMA1
  left join #RMA2 as T1 on #RMA1.SSN_IN = T1.SSN_NUMBER
  left join #RMA2 as T2 on #RMA1.SSN_Out = T2.SSN_NUMBER
where
  T1.SSN_NUMBER is not null or T2.SSN_NUMBER is not null
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...