2009-12-09 91 views
1

我有幾個表(確切地說,7個)我交叉連接的表。這部分給了我一些問題;SQL Server可選連接

表 「操作」

----------------------------------------- 
| ID | Package ID | Action Type | Message | 
----------------------------------------- 
| 40 | 100340  | 0   | OK  | 
| 41 | 100340  | 12   | Error | 
| 42 | 100340  | 2   | OK  | 

| 43 | 100341  | 4   | OK  | 
| 44 | 100341  | 0   | Error | 
| 45 | 100341  | 12   | OK  | 
----------------------------------------- 

表 「包」

---------------------- 
| ID  | Name  | 
---------------------- 
| 100340 | Testpackage | 
| 100341 | Package xy | 
---------------------- 

我完成跨joingin THM,但在沒有PackageActions指定的ID,所有對該軟件包的操作完全缺失,而不僅僅是空着 - 這正是我想要得到的結果。

所以,如果參考丟失,只留下相應的聯接的列空白或爲空字符串...:

---------------------------------------------------------------------- 
| Package ID | Name  | Action 0 | Action 2 | Action 4 | Action 12 | 
---------------------------------------------------------------------- 
| 100340  | Testpackage | OK  | OK  |   | Error  | 
| 100341  | Package xy | Error |   | OK  | OK  | 
---------------------------------------------------------------------- 

這怎麼可能?

編輯

對不起,我剛纔看到我的例子是completety錯了,我更新了它應該如何看起來像到底。

我當前的查詢看起來是這樣的(如上面所說的,就像一個實際的三倍左右,只要其中甚至包括多個表的提取物)

SELECT 
PackageTable.ID AS PackageID, 
PackageTable.Name, 
Action0Table.Message AS Action0, 
Action2Table.Message AS Action2, 
Action4Table.Message AS Action4, 
Action12Table.Message AS Action12 
FROM 
Packages AS PackageTable LEFT OUTER JOIN 
    Actions AS Action0Table ON PackageTable.ID = Action0Table.PackageID LEFT OUTER JOIN 
    Actions AS Action2Table ON PackageTable.ID = Action2Table.PackageID LEFT OUTER JOIN 
    Actions AS Action4Table ON PackageTable.ID = Action4Table.PackageID LEFT OUTER JOIN 
    Actions AS Action12Table ON PackageTable.ID = Action12Table.PackageID 
WHERE 
Action0Table.ActionType = 0 AND 
Action2Table.ActionType = 2 AND 
Action4Table.ActionType = 4 AND 
Action12Table.ActionType = 12 
+0

你能發表查詢嗎? – peacedog 2009-12-09 12:52:42

+0

請注意,您未使用CROSS JOINS,您正在使用LEFT OUTER JOINS。 – 2009-12-09 13:31:37

回答

2

正如別人所說,我有同樣的答案。

就顯示ü不同的結果

declare @Actions table(id int , packageid int, actiontype int,dt date) 
declare @Packages table(id int,name varchar(50)) 
insert into @Actions 
    select 40,100340,0,'2009/01/01 3:00pm' union all 
    select 41,100340,12,'2009/01/01 5:00pm' union all 
    select 42,100340,2,'2009/01/01 5:30pm' union all 
    select 43,100341, 4,'2009/01/02 8:00am' 
insert into @Packages 
    select 100340,'Testpackage' 

LEFT OUTER JOIN查詢

select a.packageid,p.name,a.actiontype,a.dt 
from @Actions a 
left join @Packages p 
on a.packageid = p.id 

全部參加(在這種情況下,你也會得到相同的結果)

select a.packageid,p.name,a.actiontype,a.dt 
from @Actions a 
full join @Packages p 
on a.packageid = p.id 

輸出:

packageid name actiontype dt 
100340 Testpackage 0 2009-01-01 
100340 Testpackage 12 2009-01-01 
100340 Testpackage 2 2009-01-01 
100341 NULL 4 2009-01-02 

內連接查詢(其中U不想)

select a.packageid,p.name,a.actiontype,a.dt 
from @Actions a 
join @Packages p 
on a.packageid = p.id 

輸出:

packageid name actiontype dt 
100340 Testpackage 0 2009-01-01 
100340 Testpackage 12 2009-01-01 
100340 Testpackage 2 2009-01-01 
5

那麼,爲什麼你就不能這樣做的外部JOIN,如:

SELECT `Package ID`, Name, `Action Type`, `Action Date` 
    FROM Actions 
    LEFT OUTER JOIN Packages 
    ON Actions.`Package ID` = Packages.`Package ID` 

+0

我這樣做是因爲我認爲它必須工作,但沒有做到這一點。事情是,正如我所說,我使用7個表加入一個,它不知道怎麼做正確的連接,我想也許這是因爲我誤解了外部連接: -/ – 2009-12-09 12:49:19

1

閱讀「外連接」

1

而不是INNER JOIN使用左連接。這將使它.-

4

你有一個'where'條款是排除缺少的動作記錄嗎?即使您使用外部聯接,您的where子句仍將應用,如果不匹配,則不會包含動作記錄。

編輯:問題是你的ActionType過濾器。如果沒有匹配的操作記錄,則ActionType爲空,這與您的任何過濾器都不匹配。所以,你可以在你的where子句中添加'或ActionType爲null'。我不知道您的業務需求,但這可能會包含比您想要的更多的記錄。

+0

我剛剛更新了這一點,因爲我在第一個忘了它的地方 - 我想這是錯誤是正確的,但如何擺脫它,以獲得我需要的結果? – 2009-12-09 13:04:03

+0

像這樣: WHERE (Action0Table.ActionType = 0或Action0Table.ActionType IS NULL)AND (Action2Table.ActionType = 2 OR Action2Table.ActionType IS NULL)AND (Action4Table.ActionType = 4 OR Action4Table.ActionType IS NULL )AND (Action12Table.ActionType = 12或Action12Table.ActionType IS NULL) – 2009-12-09 13:57:20

2

你是左(外)連接上的軟件包表。這意味着如果記錄不在包表中(連接條件左側的表),則不要將其包含在最終結果中。

您可以在動作表上正確(外部)連接,在這種情況下,您將獲得所有動作記錄,而不管它們是否在包表中匹配。

你可以做一個完整的(外部)連接,換句話說,把兩個表中的所有記錄都給我。

最後你可以做一個內部連接,或者兩個表中都存在的記錄。

您可能會發現在這裏畫一個維恩圖,左表爲左圓,右表爲右圓,這很有幫助。內連接因此表示圖的重疊區域。

所以,要回答你的問題,你將需要調整你的連接是完整的外連接還是右連接,這取決於你是否想看到沒有動作的包。你將需要調整你的where子句以包含許多其他海報所暗示的空行爲。儘管您可能希望添加一個附加子句,以便在表達式中排除所有操作都爲空的記錄。此外,就像編寫示例一樣,您只會看到包中的操作爲0,2,4和12的包;根據您提供的信息,這聽起來不正確。

SELECT 
PackageTable.ID AS PackageID, 
PackageTable.Name, 
Action0Table.Message AS Action0, 
Action2Table.Message AS Action2, 
Action4Table.Message AS Action4, 
Action12Table.Message AS Action12 
FROM 
Packages AS PackageTable 
    RIGHT OUTER JOIN Actions AS Action0Table ON 
    PackageTable.ID = Action0Table.PackageID 
    RIGHT OUTER JOIN Actions AS Action2Table ON 
    PackageTable.ID = Action2Table.PackageID 
    RIGHT OUTER JOIN Actions AS Action4Table ON 
    PackageTable.ID = Action4Table.PackageID 
    RIGHT OUTER JOIN Actions AS Action12Table ON 
    PackageTable.ID = Action12Table.PackageID 
WHERE 
(Action0Table.ActionType = 0 OR Action0Table.ActionType IS NULL) AND 
(Action2Table.ActionType = 2 OR Action2Table.ActionType IS NULL) AND 
(Action4Table.ActionType = 4 OR Action4Table.ActionType IS NULL) AND 
(Action12Table.ActionType = 12 OR Action12Table.ActionType IS NULL) AND 
NOT (Action0Table.ActionType IS NULL AND Action2Table.ActionType IS NULL AND 
    Action4Table.ActionType IS NULL AND Action12Table.ActionType IS NULL) 

如果您想查看沒有任何這些操作的包,則需要刪除最後的NOT子句。此外,根據數據的質量,一旦開始包含空值,您可能會開始接收重複記錄;在這種情況下,您的問題已經變得難以解決,您將需要回到我們這裏。