1

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

棘手的部分是 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 之间进行连接。

谢谢。

4

2 回答 2

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 的测试:

小部件:

------ ----------- --------
| 编号 | doodad_id | 价值 |
 ------ ----------- --------
| 1 | 1 | 1 |
| 2 | 5 | 5 |
| 3 | 3 | 3 |
| 4 | 6 | 6 |
 ------ ----------- --------

小部件历史

------ ----------- --------
| 编号 | doodad_id | 价值 |
 ------ ----------- --------
| 2 | 2 | 2 |
| 4 | 4 | 4 |
 ------ ----------- --------

小饰品:

------ ---------
| 编号 | 版本 |
 ------ ---------
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
 ------ ---------

以及查询结果:

------ -------------------------------------------------------- - --------
| 编号 | IFNULL(widgetHistory.value, widget.value) | 版本 |
 ------ -------------------------------------------------------- - --------
| 1 | 1 | 1 |
| 2 | 2 | 2 |
| 3 | 3 | 3 |
| 4 | 4 | 4 |
 ------ -------------------------------------------------------- - --------

因为它适用于表 Doodad,它也应该适用于表 Thing。

我希望这个对你有用!

于 2013-03-21T14:42:06.837 回答
0

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

于 2013-03-21T14:14:56.067 回答