При объединении таблиц адаптируйте оператор «on» в зависимости от результатов запроса. - PullRequest
0 голосов
/ 09 апреля 2020

У меня есть 2 таблицы:

  • Таблица_1 с столбцами col_A, col_B, col_ C, col_D, col_E
  • Таблица_2 с столбцами col_A, col_B, col_ C, col_D, col_F

Я хотел бы присоединиться к ним по столбцам col_A, col_B, col_ C, col_D.

Для строк в Таблице_1, которые не объединяются таким образом (поскольку они не совпадают в Таблице_2), я хотел бы присоединить их только к столбцам col_A, col_B, col_ C.

Если в Таблице_1 все еще есть строки, которые не были соединены, я хотел бы объединить их только по столбцам col_A, col_B.

И как только это будет сделано, в Таблице_1 есть еще строки, которые не присоединился, я хотел бы присоединиться к ним только в столбце col_A.

Я написал следующий скрипт, где я использую новую таблицу, чтобы получить этот результат. Есть ли более эффективный способ сделать это? Желательно, создавая представление, а не таблицу?

create table new_table (col_A nvarchar(50) , col_B nvarchar(50) , col_C nvarchar(50) 
, col_D nvarchar(50) , col_E nvarchar(50) , col_F nvarchar(50) )
go

insert into new_table
select Table_1.* , Table_2.col_F 
from Table_1 
inner join Table_2
on Table_1.col_A=Table_2.col_A 
and Table_1.col_B=Table_2.col_B 
and Table_1.col_C=Table_2.col_C 
and Table_1.col_D=Table_2.col_D
go


insert into new_table
select Table_1.* , Table_2.col_F 
from Table_1
inner join Table_2
on Table_1.col_A=Table_2.col_A 
and Table_1.col_B=Table_2.col_B 
and Table_1.col_C=Table_2.col_C
where   concat (Table_1.col_A, Table_1.col_B , Table_1.col_C , Table_1.col_D , Table_1.col_E 
        not in (select concat (col_A, col_B , col_C , col_D , col_E) from new_table)
go

insert into new_table
select Table_1.* , Table_2.col_F 
from Table_1
inner join Table_2
on Table_1.col_A=Table_2.col_A 
and Table_1.col_B=Table_2.col_B
where   concat (Table_1.col_A, Table_1.col_B , Table_1.col_C , Table_1.col_D , Table_1.col_E 
        not in (select concat (col_A, col_B , col_C , col_D , col_E) from new_table)
go

insert into new_table
select Table_1.* , Table_2.col_F 
from Table_1
inner join Table_2
on Table_1.col_A=Table_2.col_A
where   concat (Table_1.col_A, Table_1.col_B , Table_1.col_C , Table_1.col_D , Table_1.col_E 
        not in (select concat (col_A, col_B , col_C , col_D , col_E) from new_table)
go

1 Ответ

1 голос
/ 09 апреля 2020

Вы можете присоединиться к ним только на colA, а затем назначить несколько разных номеров:

WITH cte AS(

  SELECT
    CASE WHEN t1.D = t2.D THEN 100 ELSE 0 END + 
    CASE WHEN t1.C = t2.C THEN 10 ELSE 0 END + 
    CASE WHEN t1.B = t2.B THEN 1 ELSE 0 END as whatMatched,
    *
  FROM
    t1 JOIN t2 on t1.A = t2.A
)

Теперь, если строка получила 111, мы знаем, что все (ABCD) совпадают, получают 0, тогда только A matched et c ..

Таким образом, мы можем запросить только несколько строк:

SELECT * FROM cte WHERE whatmatched IN (111,11,1,0)

И, наконец, если были кратны (совпадение только с A может означать, что есть дубликаты), мы можем назначить строку Пронумеруйте их в порядке убывания и возьмите только первый ряд:

SELECT x.* FROM
  (SELECT *, ROW_NUMBER() OVER(ORDER BY whatmatched DESC) rown FROM cte WHERE whatmatched IN (111,11,1,0)) x
WHERE x.rown = 1

Если вам больше подходит использование букв

, мы можем оценить совпадения, выберите только A, AB, AB C или ABCD, затем выберите наиболее конкретный c один, посмотрев LEN gth строки соответствия:

WITH cte AS(

  SELECT
    'A' +
    CASE WHEN t1.B = t2.B THEN 'B' ELSE '' END + 
    CASE WHEN t1.C = t2.C THEN 'C' ELSE '' END + 
    CASE WHEN t1.D = t2.D THEN 'D' ELSE '' END as whatMatched,
    *
  FROM
    t1 JOIN t2 on t1.A = t2.A
)
SELECT x.* FROM
  (SELECT *, ROW_NUMBER() OVER(ORDER BY LEN(whatmatched) DESC) rown FROM cte WHERE whatmatched IN ('A','AB','ABC','ABCD')) x
WHERE x.rown = 1

Если вы хотите связи (то есть строка из t1, которая соответствует двум строкам из t2, поскольку их A / B / C одинаковы, а D отличается, используйте DENSE_RANK вместо ROW_NUMBER, чтобы они оказались привязанными к первому месту

...