【问题标题】:Fixed conditions on outer joins外连接的固定条件
【发布时间】:2012-05-31 07:16:17
【问题描述】:

这不是一个真实的例子,它一直困扰着我一段时间,我非常感谢任何能解释这种行为的人。

我有这两张桌子

MYTABLE1
ID  TYPE    NAME 
1   1       typea
2   2       typea
3   3       typea
4   4       typeb
5   5       typeb
6   6       typeb
7   7       typec
8   8       typec
9   9       typec
10  10      typed

MYTYPE
ID  NAME    DESCRIPTION
1   typea   typea with desc
2   typea   
3   typea   TYPE
4   typeb   typeb with desc
5   typeb   
6   typeb   TYPE
7   typec   typec with desc
8   typec   
9   typec   TYPE

我想要一个从两个表(mytable1 a,mytype b)返回行的 sql,其中

a) MYTABLE1.type = MYTYPE.ID 和 MYTYPE.description='TYPE'

b) MYTABLE1.type 不在 MYTYPE.id 中

a.id    a.type  a.name  b.id    b.name  b.description
3       3       typea   3       typea   TYPE
6       6       typeb   6       typeb   TYPE
9       9       typec   9       typec   TYPE
10      10      typed   null    null    null

我尝试过这种说法,但没有成功。我想要一个使用外连接,而不是联合或嵌套选择的解决方案。

例如,我使用的是 Oracle 外连接语法,但我认为通过使用标准语法并将条件 a) 放在 ON 子句中或 b) 放在 where 子句中,可以达到相同的结果

我想了解他们的“奇怪”行为,并尝试找到适用于所提供示例的行为。 对我来说最奇怪的是 SQL2。我没有写查询结果,以使问题更短,但如果需要,我可以提供。

SQL1

select * 
from 
  mytable1 a,
  mytype b
where
  a.type=b.id(+)
  and b.description ='TYPE'
order by a.id

SQL2

select * 
from 
  mytable1 a,
  mytype b
where
  a.type=b.id(+)
  and b.description(+) ='TYPE'
order by a.id

SQL3

select * 
from 
  mytable1 a,
  mytype b
where
  a.type=b.id(+)
  and (b.description ='TYPE' or b.description is null)
order by a.id

提前致谢,

【问题讨论】:

  • 如果在 oracle 中使用 (+) 进行外连接,则需要将该运算符添加到所有连接的列中。
  • 隐式连接是一种 SQL 反模式
  • 在 SQl Server 中,=+ 连接十多年来一直提供不一致的结果(它甚至在 SQl Server 2000 的联机丛书中告诉您)。在任何情况下都不应该使用它。隐式连接是一种可怕的编码实践,在 20 年前就被取代了。你为什么还在使用它们。你会使用十年前被替换的 C# 代码吗?

标签: sql oracle outer-join


【解决方案1】:

停止使用旧的笛卡尔积语法。 JOIN 语法是 ANSI-92 标准。 20年应该足以被认为是稳定的......

SELECT
  *
FROM
  myTable1    a
LEFT JOIN
  myType      b
    ON b.id = a.type
WHERE
     b.description = 'TYPE'
  OR b.id IS NULL

注意: 我确实有b.description IS NULL,但据我回忆,ORACLE 将长度为 0 的字符串视为 NULL。因此,最好测试 id 字段以判断 No Join 的情况。

【讨论】:

  • 这将返回一些错误的命中,因为 mytype 中的一些描述值甚至在外连接之前为空。应该改用“or b.id is null”
  • @ConradFrix - 那么如何从myTable 中过滤掉第 1、2、4、5、7 和 8 行?
  • @btilly - 请您详细说明这如何没有给出问题中的示例结果?第 1-9 行加入 myType 表,第 10 行不加入,但保留为 LEFT JOIN。然后 WHERE 子句过滤掉第 1、2、4、5、7、8 行并留下第 3、6、9 和 10 行。与示例中的完全一样。如果这不正确,请您用示例等详细说明?
  • @richardtz @Dems 查询的编写方式,即从 MyTable1 中获取记录以及 MyType 中的匹配记录。其中仅包括 MyType 中没有匹配记录或 MyType 描述为“TYPE”的结果。我和其他人建议这样做的方式是获取 MyTable1 中的所有记录,如果 Description 是类型,还获取 MyType 中的记录。注意:or b.id is null 在 Join 条件中永远不会有意义,因为它总是错误的。如果它是 null 它不会满足 b.id = a.type
  • @richardtz here's a sample 显示 SQL 语句及其行为方式。您需要向下滚动
猜你喜欢
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-12
  • 2020-06-26
  • 2011-03-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多