2012-03-07 66 views
0

我有3個表,Client,Tool和ClientTools。 一個客戶端可以有多個工具,因此ClientTools充當數據透視表(僅包含Id的)。3個表的外部聯接

我想要做的是,對於一個給定的客戶,有一個完整的工具列表,以及一個標誌,指示客戶是否有這個工具。

哪裏來的如此之遠是:

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 close來過濾到選定的客戶端,我的查詢只返回這個客戶端的行(所以不再進行左連接)。

我試過添加where c.Id = 123where (c.Id = 123 or c.Id is null)但沒有工作。

我錯過了什麼?

在此先感謝!

+0

你可以發佈你的WHERE子句嗎? – 2012-03-07 12:41:49

+0

完成。 (哦,歡迎最低字符數限制!) – Shimrod 2012-03-07 12:45:46

回答

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 
+0

非常感謝你馬克!我不知道我必須在連接子句中使用'and'。 – Shimrod 2012-03-07 13:03:47

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 
+0

這是一個真實案例的簡化示例。我嘗試添加此where子句,但結果是隻獲取指定的ClientId行,其他不顯示爲NULL(如預期) – Shimrod 2012-03-07 12:50:52

+0

@Shimrod - 修改我的答案,現在嘗試 – Lamak 2012-03-07 12:56:40

+0

謝謝Lamak,它似乎在做伎倆,但我更喜歡馬克的解決方案,我覺得它比你更性感(沒有冒犯)。給你一個贊成票! – Shimrod 2012-03-07 13:06:25

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 

從本質上說,你是說,客戶端(而不是工具)決定了一行是否顯示在結果集中。

+0

我想對面,顯示每個工具(每次),如果客戶端有這個工具,顯示他的行。但謝謝你的回答。 – Shimrod 2012-03-08 10:49:15