如何在没有完全外连接的情况下完成全外连接
上周我惊讶地发现,sybase 12不支持完全外连接。 但它发生在我身上,一个完整的外部联接应该与一个左外部联接相同,并与同一个sql的右外部联接联合。 有人可以想到这不会成立的理由吗?如何在没有完全外连接的情况下完成全外连接
UNION
-ing two OUTER JOIN
语句应该会导致重复的行表示您从INNER JOIN
获得的数据。您可能必须对由UNION
生成的数据集执行SELECT DISTINCT
。通常如果你不得不使用SELECT DISTINCT
这意味着它不是一个设计良好的查询(或者我听说过)。
@Josh。 'DISTINCT'不仅仅是这里所需要的;只是排除'ALL'。是的,如果你必须使用'DISTINCT'或'OUTER JOIN'这肯定表明有什么问题;与数据库设计,而不是代码。 – PerformanceDBA 2011-01-19 23:12:02
如果你将它们与UNION ALL
合并,你会得到重复。如果您仅使用UNION
而不使用ALL
,则它将过滤重复项,因此相当于全连接,但该查询也会更昂贵,因为它必须执行不同的排序。
比联盟全部贵得多,或者比本地完全外部联接贵多了? – stu 2010-01-20 16:17:42
@stu:两者。即使本地完全连接在技术上与'UNION'一样,支持完全连接的数据库引擎也可以对其进行优化。话虽如此 - 完整的连接仍然非常缓慢,值得避免,如果可以的话。我不认为我曾经使用它们。 – Aaronaught 2010-01-20 16:29:46
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;
注,其中右侧条款加入选择将结果限制为只有那些不会重复。
@Leigh。 1)不能在NOT NULL列中放置NULL,代码将不起作用2)这是oracle代码,我们在Sybase中没有'dual'或'row_ids'。 – PerformanceDBA 2011-01-19 23:05:15
1)我以为你的意思是你所说的;我没有意识到你正在说明斯图明显理解的外部联接的定义(请参阅他的帖子)。已清除2)删除'ALL'(详见其他两个答案)和'WHERE'子句。首先,你是包含愚蠢的;那么你就排除了这些蠢事;通过排除“ALL”,首先避免选择模糊更便宜,更直接,然后不需要“WHERE”。 – PerformanceDBA 2011-01-21 04:07:46
@PerformanceDBA删除'ALL'是为了让'UNION'能删除重复项。我的版本在'UNION ALL'之前消除了重复,而'UNION'版本在'UNION'上消除了它们。你可能是对的,后者可能会更便宜,这取决于数据集;无论此解决方案是否仍然有效。 – 2011-01-21 05:32:44
首先,我不知道你为什么使用12.x.在2009年4月3日获得通知后,它于2009年12月31日发布了EndOfLifed。2009年1月发布了15.0.2(第一个固体版本)。15.5好得多,于2009年12月2日发布,所以你是两个主要版本,并且至少13个月,过时了。
ASE 12.5.4具有新的Join语法。 (你没有指定,你可能会在12.5.0.3之前发布)。
DB2和Sybase没有执行
FULL OUTER JOIN
,因为您已经确定的原因是:它由LEFT ... UNION ... RIGHT
覆盖,没有ALL
。这不是“不支持”FOJ的情况;这是关键字丢失的情况。然后你有Sybase和DB2的类型,将一般不会使用外连接更不用说FOJs,因为它们的数据库更趋于规范化问题等
末,有非常普通的SQL你可以在任何版本的Sybase中使用,这些版本将提供FOJ的功能,并且在12.x上将明显更快;在15.x上稍微快一点。它有点像RANK()函数:如果你可以编写一个子查询,这是非常不必要的。
第二个原因是它不需要
FULL OUTER
,就像一些低端引擎那样,是因为新的优化器速度非常快,并且查询已完全标准化。 IE浏览器。它一次执行左和右。根据你的SARGs和DataType不匹配等等,它可能仍然需要进行排序合并,但是也可以在所有三个级别进行流式传输:磁盘I/O子系统;引擎);和网络处理程序。如果你的表是分区的,那么它在这个层次上被并行化。
如果您的服务器没有配置和结果集是非常大的,你可能需要增加
proc cache size
和number of sort buffers
。就这样。
当你尝试过时发生了什么? – gary 2010-01-18 22:35:18
我得到了什么似乎是正确的数据,但一个测试案例并不一定完全回答这个问题。 – stu 2010-01-20 16:18:16