SQL左连接两个不同的表

时间:2013-03-21 14:04:54

标签: sql sql-server-2008

我有这个表Widget,我需要加入WidgetHistory表来收集我的小部件上的历史数据。每个小部件在Doodad和Thing表中也有记录。我正在使用一个返回每个相关版本的小部件的sproc。

棘手的部分是WidgetHistory表是相对较新的,最近未修改的旧窗口小部件在WidgetHistory表中没有相应的记录。在尝试检索小部件的每个相关版本时,我正在WidgetHistory,Doodad和Thing表之间进行左连接。对于那些没有WidgetHistory记录的小部件,我想要加入Widget,Doodad和Thing表。

我已经将这个工作用于我非常有限的用例,但我对它很谨慎,因为我认为对于具有WidgetHistory记录的小部件我会得到意想不到的结果。

这是(简化)查询:

SELECT 
      w.ID,
      ISNULL(h.Title, w.Title)
      d.Version,
      t.Size
FROM dbo.Widget as w
LEFT JOIN dbo.WidgetHistory as h ON w.ID = h.ID
LEFT JOIN dbo.Doodad as d ON h.DoodadID = d.ID /*!*/ OR w.DoodadID = d.ID
LEFT JOIN dbo.Thing as t ON h.ThingID = t.ID /*!*/ OR w.ThingID = t.ID

我所怀疑的部分是什么之后!最后两个连接。我知道我可以在Widget,Doodad和Thing之间单独进行一系列左连接,但这似乎过多(但可能不是?)。

对这个或更好的策略的任何想法?同样,我想在WidgetHistory,Doodad和Thing之间进行左连接,除非小部件不存在WidgetHistory记录,并且在这种情况下,在Widget,Doodad和Thing之间进行连接。

感谢。

2 个答案:

答案 0 :(得分:1)

我试过MySQL,我想我得到了一个解决方案。希望它也能在SQL Server上运行:

SELECT 
  w.ID,
  ISNULL(h.Title, w.Title)
  d.Version,
  t.Size
FROM dbo.Widget as w
LEFT JOIN dbo.WidgetHistory as h ON w.ID = h.ID
LEFT JOIN dbo.Doodad as d ON d.ID = ISNULL(h.DoodadID, w.DoodadID) 
LEFT JOIN dbo.Thing as t ON t.ID = ISNULL(h.ThingID, w.ThingID)

我不得不在MySQL上使用IFNULL函数,而不是ISNULL,但两者似乎都以相同的方式工作。

我对MySQL的测试:

窗口小部件:

 ------ ----------- -------
| id   | doodad_id | value |
 ------ ----------- -------
|    1 |         1 |     1 |
|    2 |         5 |     5 |
|    3 |         3 |     3 |
|    4 |         6 |     6 |
 ------ ----------- -------

WidgetHistory

 ------ ----------- -------
| id   | doodad_id | value |
 ------ ----------- -------
|    2 |         2 |     2 |
|    4 |         4 |     4 |
 ------ ----------- -------

装饰物:

 ------ ---------
| id   | version |
 ------ ---------
|    1 |       1 |
|    2 |       2 |
|    3 |       3 |
|    4 |       4 |
|    5 |       5 |
|    6 |       6 |
 ------ ---------

查询结果:

 ------ ------------------------------------------- ---------
| id   | IFNULL(widgetHistory.value, widget.value) | version |
 ------ ------------------------------------------- ---------
|    1 |                                         1 |       1 |
|    2 |                                         2 |       2 |
|    3 |                                         3 |       3 |
|    4 |                                         4 |       4 |
 ------ ------------------------------------------- --------- 

因为它适用于Doodad表,所以它也应该适用于表格。

我希望它适合你!

答案 1 :(得分:0)

我自己使用联合查询。上半部分将加入WidgetHistory,而下半部分则不会。