当连接表时,根据查询结果调整“ on”语句

问题描述 投票:0回答:1

我有2张桌子:

  • 具有列col_A,col_B,col_C,col_D,col_E的表_1
  • 具有列col_A,col_B,col_C,col_D,col_F的表_2

我想将它们加入到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
sql-server conditional-statements inner-join
1个回答
1
投票

您可以在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匹配,依此类推。

所以我们只能要求一些行:

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,ABC或ABCD,然后通过查看匹配字符串的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,这样它们最终会并列第一名

© www.soinside.com 2019 - 2024. All rights reserved.