OUTER JOIN 结果缺少行,没有 WHERE 子句(找到解决方法)

Posted

技术标签:

【中文标题】OUTER JOIN 结果缺少行,没有 WHERE 子句(找到解决方法)【英文标题】:OUTER JOIN result is missing rows, no WHERE clause (Workaround found) 【发布时间】:2012-09-24 22:03:30 【问题描述】:

在底部更新。

我正在尝试做一个自外连接,对于每条记录,返回它和所有其他在它之后发生的记录,如果它本身是最新的记录,则返回 NULL。这是我的sql代码:

SELECT A.[CR#], A.REGIS_STATUSDATE, B.REGIS_STATUSDATE
FROM CR_ADMIN_REGIS_STATUS A LEFT OUTER JOIN CR_ADMIN_REGIS_STATUS B
ON A.[CR#]=B.[CR#] AND A.REGIS_STATUSDATE < B.REGIS_STATUSDATE

我的问题是,对于给定的 [CR#],当 A.REGIS_STATUSDATE 是最大值(因此 B.REGIS_STATUSDATE 不能大于它)时,该行不包含在我的结果中。

例如,如果 CR_ADMIN_REGIS_STATUS 如下所示:

CR#   REGIS_STATUSDATE
1     5/1/12
1     5/2/12
1     5/3/12
2     5/1/12
2     5/2/12

我希望我的查询结果是

CR#   A.REGIS_STATUSDATE B.REGIS_STATUSDATE
1     5/1/12             5/2/12
1     5/1/12             5/3/12
1     5/2/12             5/3/12
1     5/3/12             NULL
2     5/1/12             5/2/12
2     5/2/12             NULL

相反,我得到了这个:

CR#   A.REGIS_STATUSDATE B.REGIS_STATUSDATE
1     5/1/12             5/2/12
1     5/1/12             5/3/12
1     5/2/12             5/3/12
2     5/1/12             5/2/12

鉴于我的查询是 LEFT OUTER JOIN,并且我没有 WHERE 子句,我希望原始表中的所有行都在结果中,但事实并非如此。我在这里错过了什么?

编辑:这是在 Access 2007 中

更新:我决定看看如果我将表 CR_ADMIN_REGIS_STATUS 的部分复制到一个单独的表中并针对它运行我的查询会发生什么。即使我刚刚直接将整个表复制到新表中(手动),查询仍然有效!这只是实际复制和粘贴时的情况,但当我 SELECT * INTO 另一个表时,问题会持续存在。 最终我发现,如果我对

运行查询
SELECT *
FROM CR_ADMIN_REGIS_STATUS
UNION ALL SELECT TOP 1 * 
FROM CR_ADMIN_REGIS_STATUS;

我的查询返回了所需的结果,而不是 CR_ADMIN_REGIS_STATUS 本身。奇怪的。我也对一个从一开始就有效的类似表进行了类似的查询,所以这似乎是一个仅限于这个表的问题。

【问题讨论】:

这也让我摸不着头脑 在 MS Access 2010 中运行您的查询,我得到了您的预期结果。 【参考方案1】:

你没有错过任何东西。 如果发生这种情况,那就是错误。

MS-Access 使用的引擎有几个错误。我在具有“复杂”ON 条件的连接中看到了类似的无效行为。查看 Access 给出错误结果的另一个 SO 问题:Why does my left join in Access have fewer rows than the left table?

您可以在 SQL-Server、Oracle、Postgres 甚至 mysql 中尝试使用相同数据的查询,您将获得正确的预期结果。


作为一种解决方法,您可以尝试使用UNION 重写查询,但永远无法确定其正确性:

SELECT A.[CR#], A.REGIS_STATUSDATE, B.REGIS_STATUSDATE
FROM CR_ADMIN_REGIS_STATUS A 
  INNER JOIN CR_ADMIN_REGIS_STATUS B
    ON  A.[CR#]=B.[CR#] 
    AND A.REGIS_STATUSDATE < B.REGIS_STATUSDATE

UNION ALL

SELECT A.[CR#], A.REGIS_STATUSDATE, NULL
FROM CR_ADMIN_REGIS_STATUS A 
WHERE NOT EXISTS
      ( SELECT *
        FROM CR_ADMIN_REGIS_STATUS B
        WHERE A.[CR#]=B.[CR#] 
          AND A.REGIS_STATUSDATE < B.REGIS_STATUSDATE
      ) ;

【讨论】:

我在 MS Access 中得到了预期的结果。 感谢您的快速回答,尽管听到这个错误令人失望。我会尝试你的解决方法。 @Remou:当我回答另一个问题时,我做了一些测试,有 2 个表和很少的行,每行 2 或 3 个。具有ON a.id=b.id OR a.x IS NULL 或类似条件的查询会产生非常奇怪的结果。 @Remou:我也在 2007 版本中测试过。但这种情况似乎比另一种情况更正常和普遍。我对这个错误感到相当惊讶,但这更令人惊讶,因为没有涉及 Null。

以上是关于OUTER JOIN 结果缺少行,没有 WHERE 子句(找到解决方法)的主要内容,如果未能解决你的问题,请参考以下文章