没有匹配时表连接然后使用定义的字符串

时间:2017-06-29 14:20:33

标签: sql-server

我希望将一个表加入另一个表,但是当没有匹配项时,我想使用特定的字符串值来匹配,而不是我知道会有匹配的值。

例如,采用这种结构

declare @A table (id int identity(1,1), category varchar(4))
declare @B table (category varchar(4), name varchar(10))

insert @A values ('AB')
insert @A values ('AB')
insert @A values ('AB')
insert @A values ('AB')
insert @A values ('AC')
insert @A values ('AD')

insert @B values ('AB', 'Fred')
insert @B values ('AC', 'Bob')
insert @B values ('else', 'Jane')
insert @B values ('else', 'Mary')

如果我使用了简单的连接:

select a.id, a.category, b.category, b.name
from @A a 
inner join @B b on a.category = b.category

然后前5个记录将匹配,我最终得到:

1   AB  AB  Fred
2   AB  AB  Fred
3   AB  AB  Fred
4   AB  AB  Fred
5   AC  AC  Bob

然而,我想做的是,最后一张没有匹配记录的记录我想更换类别" AD"在表格@A with" else"这样它匹配表@B中的两个记录并返回:

1   AB      AB      Fred
2   AB      AB      Fred
3   AB      AB      Fred
4   AB      AB      Fred
5   AC      AC      Bob
6   else    else    Jane
6   else    else    Mary

更新

在某些情况下,@ A表格不包含匹配的记录,所以我不认为可以使用正确的联接,因为我不想要@B的所有记录。例如,如果@A没有" AC"记录并且刚刚包含:

insert @A values ('AB')
insert @A values ('AB')
insert @A values ('AB')
insert @A values ('AB')
insert @A values ('AB')
insert @A values ('AD')

然后输出为:

1   AB      AB      Fred
2   AB      AB      Fred
3   AB      AB      Fred
4   AB      AB      Fred
5   AB      AB      Fred
6   else    else    Jane
6   else    else    Mary

返回正确数据的各种选项是什么?

5 个答案:

答案 0 :(得分:2)

您可以使用RIGHT JOIN而不是INNER JOIN。这将为您提供表B中的所有行。

然后,我会将您的查询参数更改为使用“b.category”而不是“a.category”,因为它不会总是匹配。

最后,当ID不匹配时,您可以使用ISNULL()。

select a.id, ISNULL(a.category, b.category), b.category, b.name
from @A a 
    RIGHT join @B b on a.category = b.category

但是你的a.ID仍然是null。如果你想在表A中有一个超过id的最大值,你也可以这样做。

select ISNULL(a.id, (SELECT MAX(id) from @a)), ISNULL(a.category, b.category), b.category, b.name
from @A a 
    RIGHT join @B b on a.category = b.category

因此,如果在您的更新中,您的意思是只有B中的行,即AITH中有匹配的行,或者“else”作为类别,那么您可以这样做:

select ISNULL(a.id, (SELECT MAX(id) from @a)), ISNULL(a.category, 
b.category), b.category, b.name
from @A a 
    RIGHT join @B b on a.category = b.category
where a.id is not null or b.category = 'else'

但我不明白你如何以“AB”作为他的类别获得“Bob”。

结果:

1   AB      AB      Fred
2   AB      AB      Fred
3   AB      AB      Fred
4   AB      AB      Fred
5   else    else    Jane
5   else    else    Mary

答案 1 :(得分:0)

您正在寻找Right Join,因为您希望在所有情况下填充表@B。

select a.id, ISNULL(a.category,b.category) category, b.category, b.name
from @A a 
right join @B b on a.category = b.category

输出:

id          category category name
----------- -------- -------- ----------
1           AB       AB       Fred
2           AB       AB       Fred
3           AB       AB       Fred
4           AB       AB       Fred
5           AC       AC       Bob
NULL        else     else     Jane
NULL        else     else     Mary

答案 2 :(得分:0)

你必须加入@B两次。第一次“正常”,然后当b1为空且b2.category尚未加入“正常”连接时。像这样:

declare @A table (id int identity(1,1), category varchar(4))
declare @B table (category varchar(4), name varchar(10))

insert @A values ('AB')
insert @A values ('AB')
insert @A values ('AB')
insert @A values ('AB')
insert @A values ('AC')
insert @A values ('AD')

insert @B values ('AB', 'Fred')
insert @B values ('AC', 'Bob')
insert @B values ('else', 'Jane')
insert @B values ('else', 'Mary')


select
    a.id
    , coalesce(b2.category, a.category) as category1
    , coalesce(b2.category, b1.category) as category2
    , coalesce(b2.name, b1.name) as name
from @A a
    left join @b b1 on a.category = b1.category
    left join @b b2 on b1.category is null and b2.category not in (select
                                                                    a.category
                                                                from @A a
                                                                    inner join @B b on a.category = b.category)

答案 3 :(得分:0)

为了获得id,我推荐这个解决方案:

select a.id, a.category, b.category, b.name
from @A a 
inner join @B b on a.category = b.category
union all
select nomatch.id, b.category, b.category, b.name
from (select a.id
   from @A a 
   left join @B b on a.category = b.category
   where b.category is null ) nomatch
join @b  
where b.category = 'else'

我不完全确定语法,但这就是想法。

答案 4 :(得分:0)

    declare @A table (id int identity(1,1), category varchar(4))  
    declare @B table (category varchar(4), name varchar(10))  
    Declare @id int = 0  **--added line**  
    insert @A values ('AB')  
    insert @A values ('AB')  
    insert @A values ('AB')  
    insert @A values ('AB')  

insert @A values ('AC')  
insert @A values ('AD')  
SELECT @id = @@IDENTITY; **----added line**  
insert @B values ('AB', 'Fred')  
insert @B values ('AC', 'Bob')  
insert @B values ('else', 'Jane')  
insert @B values ('else', 'Mary')  

select  a.category, b.category, b.name,  
case   
when a.ID IS not NULL then a.id   
else  @id   
end as ID  
from @A a   
right join @B b on a.category = b.category