3个表上的外连接

时间:2012-03-07 12:38:08

标签: sql sql-server join

我有3个表,Client,Tool和ClientTools。 一个客户端可以有多个工具,因此ClientTools充当数据透视表(仅包含Id)。

对于给定的客户,我想要的是拥有完整的工具列表,以及指示客户是否拥有此工具的标志。

我到目前为止的地方是:

select      t.Id as [ToolId],
            t.Name as [ToolName],
            Cast(case when c.Id is NULL then 0 else 1 end as bit) as [HasThisTool],
from        Tool t
Left join   ClientTools ct
on          t.Id = ct.ToolId
Left Join   Client c
on          ct.ClientId = c.Id

哪个正确地为我提供了所有工具,但适用于所有客户端(当多个客户拥有此工具时复制工具行)。

但是一旦我使用了接近过滤到所选客户端的地方,我的查询只会返回此客户端的行(因此不再进行左连接)。

我尝试添加where c.Id = 123where (c.Id = 123 or c.Id is null)但没有效果。

我错过了什么?

提前致谢!

3 个答案:

答案 0 :(得分:1)

在您的查询中,如果您没有检索客户端的名称,则无需加入该表(但这不是真正的问题)。试试这个:

select      t.Id as [ToolId],
            t.Name as [ToolName],
            Cast(case when ct.Id is NULL then 0 else 1 end as bit) as [HasThisTool]
from        Tool t
Left join   (SELECT * FROM ClientTools WHERE ClientId = @ClientId) ct
on          t.Id = ct.ToolId

答案 1 :(得分:1)

尝试:

select      t.Id as [ToolId],
            t.Name as [ToolName],
            Cast(case when ct.Id is NULL then 0 else 1 end as bit) as [HasThisTool]
from        Tool t
Left join   ClientTools ct
on          t.Id = ct.ToolId and ct.ClientId = @ClientId

答案 2 :(得分:0)

如果您切换表格的顺序,它应该有效:

select      t.Id as [ToolId],
            t.Name as [ToolName],
            Cast(case when t.Id is NULL then 0 else 1 end as bit) as [HasThisTool],
from        Client c
Left join   ClientTools ct
on          c.Id = ct.ClientId
Left Join   Tool t
on          ct.ToolId = t.Id
where       c.id = 123

从本质上讲,您说客户端(而不是工具)决定了行是否显示在结果集中。