Sql 子查询的外部联接的替代方案?

Sql 子查询的外部联接的替代方案?,sql,oracle,scalar-subquery,Sql,Oracle,Scalar Subquery,显然,Oracle不允许对子查询进行外部联接。对于表A上的每一行,我都在尝试查找表B上具有相同ID和最新日期的行 大概是这样的: SELECT a.*, b.date, b.val1, b.val2 FROM a, b WHERE b.id (+) = a.id AND b.date (+) = (SELECT MAX(b.date) FROM a, b WHERE a.id = b.id); 在b.date上删除外部联接(+)允许对其进行分析,但是当表b上没有行时,不会返回任何行。在这种

显然,Oracle不允许对子查询进行外部联接。对于表A上的每一行,我都在尝试查找表B上具有相同ID和最新日期的行

大概是这样的:

SELECT a.*, b.date, b.val1, b.val2
FROM a, b
WHERE b.id (+) = a.id
  AND b.date (+) = (SELECT MAX(b.date) FROM a, b WHERE a.id = b.id);
在b.date上删除外部联接(+)允许对其进行分析,但是当表b上没有行时,不会返回任何行。在这种情况下,我需要查询只返回NULL。有办法解决这个问题吗


谢谢编辑:您可以将最长日期保存到变量中

DECLARE @maxDate as datetime
SET @maxDate = (SELECT MAX(date) FROM b)

SELECT a.*, b.date, b.val1, b.val2
FROM a
LEFT OUTER JOIN b ON a.id = b.id
  AND b.date = @maxDate

这可能比艾伦的答案更有效或更无效,这取决于A的行数是否比B多(反之亦然)。如果B有很多行,那么查询它两次(我的答案就是这样)可能不是最好的解决方案。

标量子查询怎么样

select a.*, (select max(b.date) from b where b.id = a.id) as b_date
from a;

我想你想要的是:

SELECT a.*, b.date, b.val1, b.val2
FROM a
LEFT JOIN b ON b.id = a.id
WHERE (b.date is null 
       or b.date = (SELECT MAX(b2.date) FROM b b2 WHERE a.id = b2.id));
这样,外部联接只在
id
上执行。然后我们过滤掉
b.date
不是
a
中相应行的
max
的所有行


另外,您会注意到我从子查询中删除了
a
。正如最初编写的那样,子查询返回了
b
中最大的日期,该日期在
a
中有相应的行。相同的值将用于外部查询的每一行。修改后的版本使子查询与外部查询关联(即,它将为返回的每一行获得相应的
max(date)

我已经投票赞成Allan的答案,但只是为了演示另一种方法,下面是如何使用分析函数实现的:

SELECT * FROM (
  SELECT a.*, b.date, b.val1, b.val2,
    ROW_NUMBER() over (PARTITION BY a.id ORDER BY b.date DESC) r
  FROM a LEFT JOIN b ON a.id=b.id
)
WHERE r=1


这将只包括每个
a.id
的一行,即使有多个
b
行具有最长日期。要包含所有这些内容,请将
行号
更改为
排名

为什么不能使用
按b排序。日期描述
谢谢-我需要从b中选择几个其他字段。更新了问题。这没关系,因为您关心的是最新日期的行,您仍然可以使用order byok。我还需要从另一个表C中选择一些匹配的行。您能给出一个如何工作的示例吗?谢谢你不是很清楚你想要什么。如果不是最大值,是否希望B的日期为空?或者,如果日期不是最大值,您希望B中的所有内容都为null吗?他需要B中的其他一些列,并且(我认为)他只希望对B中具有最大日期的行执行联接。我认为您是对的-但是当我回答他的问题时,我不希望B中的任何其他列,这是后来添加的!否-出现错误“列可能未外部联接到子查询”。OP已指定这是Oracle问题。这似乎是SQL Server解决方案。@艾伦:是的,我通常不使用Oracle。这是非标准SQL吗?Oracle不使用@for变量,也不允许在不使用游标的情况下返回过程块的结果集。啊,我每天都学到一些新东西。我远非SQL大师。谢谢你的知识。这是一个很好的答案,我对此投了赞成票。根据每个表中有多少行,它可能比我的答案更有效,也可能比我的答案更有效。@DouglasBarbin:我们的答案实际上提供了不同的结果。您的
max(date)
将在所有
b
表中获得一个
max(date)
,而我的
max(date)
将针对每个唯一的
b.id
。基于正确解释的问题还不清楚。我只是在OP上评论了一些类似的东西。我的也不同,它不会对A中的行执行与B的联接,其中日期不是表的最大值。你的查询总是在id上加入,然后根据B中的日期是否是给定id的最大日期来删除行。因此,这两个查询实际上比我最初意识到的有点不同。我对此进行了投票,因为它可能比Allan的答案更优,因为执行
(或)