2009-12-09 97 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子句。此外,根据数据的质量,一旦开始包含空值,您可能会开始接收重复记录;在这种情况下,您的问题已经变得难以解决,您将需要回到我们这里。