如何在没有完全外连接的情况下完成全外连接

问题描述:

上周我惊讶地发现,sybase 12不支持完全外连接。 但它发生在我身上,一个完整的外部联接应该与一个左外部联接相同,并与同一个sql的右外部联接联合。 有人可以想到这不会成立的理由吗?如何在没有完全外连接的情况下完成全外连接

+0

当你尝试过时发生了什么? – gary 2010-01-18 22:35:18

+0

我得到了什么似乎是正确的数据,但一个测试案例并不一定完全回答这个问题。 – stu 2010-01-20 16:18:16

UNION -ing two OUTER JOIN语句应该会导致重复的行表示您从INNER JOIN获得的数据。您可能必须对由UNION生成的数据集执行SELECT DISTINCT。通常如果你不得不使用SELECT DISTINCT这意味着它不是一个设计良好的查询(或者我听说过)。

+1

@Josh。 'DISTINCT'不仅仅是这里所需要的;只是排除'ALL'。是的,如果你必须使用'DISTINCT'或'OUTER JOIN'这肯定表明有什么问题;与数据库设计,而不是代码。 – PerformanceDBA 2011-01-19 23:12:02

如果你将它们与UNION ALL合并,你会得到重复。如果您仅使用UNION而不使用ALL,则它将过滤重复项,因此相当于全连接,但该查询也会更昂贵,因为它必须执行不同的排序。

+0

比联盟全部贵得多,或者比本地完全外部联接贵多了? – stu 2010-01-20 16:17:42

+0

@stu:两者。即使本地完全连接在技术上与'UNION'一样,支持完全连接的数据库引擎也可以对其进行优化。话虽如此 - 完整的连接仍然非常缓慢,值得避免,如果可以的话。我不认为我曾经使用它们。 – Aaronaught 2010-01-20 16:29:46

+1

Aaronaught。这是不正确的。 Sybase ASE 12为此目的非常快速,它使用内部工作表和排序缓冲区。企业级引擎与免费软件完全不同。 – PerformanceDBA 2011-01-19 10:43:17

UNION ALL左连接使用正确的连接,但将右连接限制为仅基本表中不存​​在的行(如果连接存在,它们在表中不会为空时,在连接上返回null)。

对于此代码,您需要创建两个表t1和t2。 t1应该有一列名为c1,其中五行包含值1-5。 t2也应该有一个包含值2-6的五行的c1列。

完全外部联接:

select * from t1 full outer join t2 on t1.c1=t2.c1 order by 1, 2; 

全外连接等效:

select t1.c1, t2.c1 from t1 left join t2 on t1.c1=t2.c1 
union all 
select t1.c1, t2.c1 from t1 right join t2 on t1.c1=t2.c1 
where t1.c1 is null 
order by 1, 2; 

注,其中右侧条款加入选择将结果限制为只有那些不会重复。

+1

@Leigh。 1)不能在NOT NULL列中放置NULL,代码将不起作用2)这是oracle代码,我们在Sybase中没有'dual'或'row_ids'。 – PerformanceDBA 2011-01-19 23:05:15

+1

1)我以为你的意思是你所说的;我没有意识到你正在说明斯图明显理解的外部联接的定义(请参阅他的帖子)。已清除2)删除'ALL'(详见其他两个答案)和'WHERE'子句。首先,你是包含愚蠢的;那么你就排除了这些蠢事;通过排除“ALL”,首先避免选择模糊更便宜,更直接,然后不需要“WHERE”。 – PerformanceDBA 2011-01-21 04:07:46

+0

@PerformanceDBA删除'ALL'是为了让'UNION'能删除重复项。我的版本在'UNION ALL'之前消除了重复,而'UNION'版本在'UNION'上消除了它们。你可能是对的,后者可能会更便宜,这取决于数据集;无论此解决方案是否仍然有效。 – 2011-01-21 05:32:44

  1. 首先,我不知道你为什么使用12.x.在2009年4月3日获得通知后,它于2009年12月31日发布了EndOfLifed。2009年1月发布了15.0.2(第一个固体版本)。15.5好得多,于2009年12月2日发布,所以你是两个主要版本,并且至少13个月,过时了。

  2. ASE 12.5.4具有新的Join语法。 (你没有指定,你可能会在12.5.0.3之前发布)。

  3. DB2和Sybase没有执行FULL OUTER JOIN,因为您已经确定的原因是:它由LEFT ... UNION ... RIGHT覆盖,没有ALL。这不是“不支持”FOJ的情况;这是关键字丢失的情况。

  4. 然后你有Sybase和DB2的类型,将一般不会使用外连接更不用说FOJs,因为它们的数据库更趋于规范化问题等

  5. 末,有非常普通的SQL你可以在任何版本的Sybase中使用,这些版本将提供FOJ的功能,并且在12.x上将明显更快;在15.x上稍微快一点。它有点像RANK()函数:如果你可以编写一个子查询,这是非常不必要的。

  6. 第二个原因是它不需要FULL OUTER,就像一些低端引擎那样,是因为新的优化器速度非常快,并且查询已完全标准化。 IE浏览器。它一次执行左和右。

  7. 根据你的SARGs和DataType不匹配等等,它可能仍然需要进行排序合并,但是也可以在所有三个级别进行流式传输:磁盘I/O子系统;引擎);和网络处理程序。如果你的表是分区的,那么它在这个层次上被并行化。

  8. 如果您的服务器没有配置结果集是非常大的,你可能需要增加proc cache sizenumber of sort buffers。就这样。