2014-08-27 139 views
1

我喜歡這些表:SQL外部連接?

Fields (ID int, Name varchar(20)) 

ID  Name 
=============== 
1  FieldName 
2  FeildDesc 

Container (ID int, Name varchar(100)) 

ID  Name 
==================================== 
1  C1  
2  C2 
3  C3 

ContainerField (ContainerId int, FieldId int, FieldValue varchar(100)) 

ContainerId FieldId FieldValue 
==================================== 
1    1   Container1 
1    2   Container1 Desc 
2    1   Container2 
2    2   Container3 Desc 
3    1   Container3 

我希望有我的結果是這樣的:

ContainerId Name   Desc 
=================================== 
1    Container1 Container1 Desc 
2    Container2 Container2 Desc 
3    Container3 NULL 

我試圖做LEFT OUTER ContainerField和領域,而且沒」之間的連接似乎沒有工作。如果有人能幫忙,我會很感激。

+3

「*未seemt工作*」 是不可接受的錯誤描述 – 2014-08-27 19:57:13

+3

怎麼沒工作?你試過的查詢是什麼? – Barmar 2014-08-27 19:57:14

回答

3

加入表格兩次,一次爲名稱,一次爲描述。

select 
    c.Id as ContainerId, 
    cfn.FieldValue as Name, 
    cfd.FieldValue as Desc 
from 
    Container c 
    left join ContainerField cfn 
    on cfn.ContainerId = c.ID and cfn.FieldId = 1 
    left join ContainerField cfd 
    on cfd.ContainerId = c.ID and cfd.FieldId = 2 

正如您所看到的,不是組或聚合。另外,查詢中並不需要Fields tabel本身,不過在數據庫中使用Fields tabel本身是很好的,因爲它會強制引用完整性(如果您擁有正確的密鑰)並提供一種文檔。但你也可以使用枚舉。

或者,如果您不只有兩個字段,但是它們的數量未知,您可能需要考慮pivot tables。我必須承認,對於這些人我並不是很擅長,特別是在TSQL中,所以我會爲您提供一個鏈接供您探索:http://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx或者希望別人能給你一個具體的例子。

0

你做的似乎只是需要一個left join

select c.id, c.name, cf.FieldValue 
from Container c join 
    ContainerField cf 
    on cf.ContainerId = c.id and cf.FieldId = 2; 

當然,在你的問題中的數據是有點誤導。我假設name列意在來自Container表。

1

不需要外連接,內連接就可以做到。您也沒有使用Container中的任何內容(如果您想顯示容器名稱而不是ID,則可以使用它進行內部連接以獲取該內容)。

SELECT c.id AS ContainerID, 
     MAX(CASE WHEN f.name = 'FieldName' THEN c.FieldValue END) AS Name, 
     MAX(CASE WHEN f.name = 'FieldDesc' THEN c.FieldValue END) AS `Desc` 
FROM ContainerField AS c 
JOIN Fields AS f ON c.FieldID = f.id 
GROUP BY ContainerID 

DEMO

請注意,您在Fields表有一個拼寫錯誤:FeildsDesc應該是FieldsDesc

+0

這將工作。我不認爲像這樣「濫用」團隊是最乾淨的方式,但是再次,我已經在SO回答和生產代碼中使用了這個,所以我們不要成爲僞君子。+1 :-) – GolezTrol 2014-08-27 20:29:40

0

我覺得這是你所追求的:

SELECT t1.ContainerId, t1.FieldValue, t2.FieldValue 
FROM ContainerField t1 
LEFT JOIN ContainerField t2 ON t1.ContainerId = t2.ContainerId 
     AND t1.FieldId = 1 and t2.FieldId = 2 

EDIT(SQL Fiddle):

SELECT DISTINCT t1.ContainerId, 
(
    SELECT t2.FieldValue FROM ContainerField t2 
    WHERE t2.FieldId = 1 AND t1.ContainerId = t2.ContainerId 

) AS [Name], 
(
    SELECT t3.FieldValue FROM ContainerField t3 
    WHERE t3.FieldId = 2 AND t1.ContainerId = t3.ContainerId 
) AS [Desc] 
FROM ContainerField t1 
+0

感謝您的回覆,但是這並不顯示最後一行的Desc列爲NULL。 – notlkk 2014-08-27 20:14:42

+0

我認爲這可能工作,如果你移動條件't1.FieldId = 1'到where子句。如果你不這樣做,那麼我認爲沒有條件阻止t1返回'type 2'字段。 – GolezTrol 2014-08-27 20:21:14

+0

** @ notlkk **,我更新了我的答案,以表明您可以通過表格('ContainerField')獲得所需的結果。看我的編輯。 – Linger 2014-08-27 20:23:33

1

可能會在我的兩分錢,以及拋出。這會讓你得到你所需要的。這是在Oracle中完成的,但應該也一樣。

編輯:SQL Fiddle Demo作爲一個工作的例子。

Select * From (

WITH 
/* Example Tables.*/ 
Container As 
(
    Select 1 as ID, 'C1' as Name From Dual Union All  
    Select 2 as ID, 'C2' as Name From Dual Union All 
    Select 3 as ID, 'C3' as Name From Dual 
) 

,ContainerField as 
(
    Select 1 as ContainerId, 1 as FieldId, 'Container1  ' as FieldValue From Dual UNION ALL 
    Select 1 as ContainerId, 2 as FieldId, 'Container1 Desc' as FieldValue From Dual UNION ALL 
    Select 2 as ContainerId, 1 as FieldId, 'Container2  ' as FieldValue From Dual UNION ALL 
    Select 2 as ContainerId, 2 as FieldId, 'Container2 Desc' as FieldValue From Dual UNION ALL 
    Select 3 as ContainerId, 1 as FieldId, 'Container3  ' as FieldValue From Dual 
) 

/*Code*/ 
Select 
    C.ID, 
    Max(Case When CF.FieldId = 1 Then FieldValue End) as Name, 
    Max(Case When CF.FieldId = 2 Then FieldValue End) as Descrption 
From 
    Container C 
    Left Join ContainerField CF on C.ID = CF.ContainerID 

Group By 
    C.ID, 
    C.Name 
Order By 
    C.ID 
) 

輸出:

CONTAINERID  NAME  DESCRPTION 
1    Container1 Container1 Desc 
2    Container2 Container2 Desc 
3    Container3  
+1

您可能會發現http://sqlfiddle.com/有趣。然後您可以鏈接到查詢。我只是說因爲我在這裏有很多像你這樣的答案。我向你保證這樣更簡單,看起來更「專業」 – SQLMason 2014-08-27 20:18:35

+1

通過使用'CF.ContainerID'你有一點作弊,如果沒有匹配的ContainerField作爲字段類型'Name'的容器,將會失敗。你應該'選擇','按組'和'按''C.ID'來代替。或者,如果您假設總是有一個名稱字段,那麼將第一個聯接更改爲「內部聯接」以使該假設變得清晰(並使查詢更加優化)。一旦你解決了這個問題,你的答案基本上和@ Barmar的答案一樣。 :) – GolezTrol 2014-08-27 20:25:53

+0

@GolezTrol好抓!我通常以這種方式進行分組,但是我認爲我放了'ContainerID',這當然是不可靠的。 – Phillip 2014-08-27 20:42:20