2

我有表格(列)A(a)B(b, a). 字段a是primary in Ab是primary in BA表示一组类,B表示一组元素,每个元素都是一个类的一部分。任务是检索所有类 ( A.a) 是第一列,这些类的元素在第二列。如果某个类不包含元素,则应在第二列中使用 null 检索它。

正确的查询是:

select A.a, B.b from A left join B on A.a = B.a

这正是我需要的。但是,在阅读了左连接的文档后,我尝试使用查询手动重复此结果:

select B.a, B.b as "b" from B
union
select A.a, null as "b" from A
where A.a not in (select B.a from B)

第一行选择我需要的所有对,第 3-4 行专门选择那些未在表中显示B且第二列为空的类。这两个查询返回不同的行数,我不明白为什么。有人可以解释一下吗?是我对左加入行为的理解还是其他什么?(不幸的是,我对执行它的服务器没有太多访问权限,我可能只能看到返回的行数。)

4

3 回答 3

1

(注意:这是第一次作为评论发布。)

如果B.a可以有 NULL 并且某些行在该列中确实有 NULL,则第二个查询的第二部分将不返回任何内容。那是因为x NOT IN (list)基本上转化为

 x <> value1 AND x <> value2 AND ...

并且当至少其中一个值为 NULL 时,该特定<>谓词的计算结果为 UNKNOWN,如果所有其他谓词的计算结果都为 TRUE,则整个条件也变为 UNKNOWN(根据三值逻辑,TRUE AND UNKNOWN 产生 UNKNOWN )。

根据B包含 NULL 的行与B.a任何A行未引用的行之间的比率B,整个第二个查询可以返回比第一个查询更多更少的行,尽管这两个查询也可能返回相同数量的行

另一种可能性是存在对不存在的A行的引用B(这意味着没有外键来保证引用完整性)。如果有这样的行,第一个查询将返回比第二个更少的行,因为它将排除无效引用,而第二个查询将包含它们。

于 2013-09-23T22:08:00.850 回答
0

假设您有这样的数据:

Table A
1
2
3
4

Table B
1, A
1, B
2, A
3, F
3, F

UNION将消除出现的任何重复结果。在这种情况下,“3,F”只列出一次。否则结果将是相同的。AUNION ALL应该返回相同的确切结果。

请参阅此SQL Fiddle 示例

于 2013-09-23T02:35:47.623 回答
0

Union 会将所有空值视为单个空值,这可能不是您所期望的。有两种方法可以解决这个问题:

1. Use UNION ALL
2. Use non distinct "type Fields"...


    SELECT
          Type="Type1",
          Amount
       FROM 
         Table

       UNION

       SELECT
          Type="Type2",
          Amount
       FROM 
          Table
于 2013-09-23T02:32:23.770 回答