我有一张包含51条记录的表格。表结构如下所示:
ack_extract_id query_id cnst_giftran_key field1 value1
现在ack_extract_ids可以是8,9。 我想检查一下extract_id 9中的giftran键,而不是8中的那个。
我试过的是
SELECT *
FROM ddcoe_tbls.ack_flextable ack_flextable1
INNER JOIN ddcoe_tbls.ack_main_config config
ON ack_flextable1.ack_extract_id = config.ack_extract_id
LEFT JOIN ddcoe_tbls.ack_flextable ack_flextable2
ON ack_flextable1.cnst_giftran_key = ack_flextable2.cnst_giftran_key
WHERE ack_flextable2.cnst_giftran_key IS NULL
AND config.ack_extract_file_nm LIKE '%Dtl%'
AND ack_flextable2.ack_extract_id = 8
AND ack_flextable1.ack_extract_id = 9
但它正在给我0条记录。理想情况下,right为null的左连接应该返回右侧表中不存在cnst_giftran_key的记录,对吗?
我在这里缺少什么?
答案 0 :(得分:3)
在where子句(在您的情况下为ack_flextable2.ack_extract_id
)中测试左连接表中的列时,强制该连接的行为就像它是内连接一样。相反,将该测试移动到连接条件的一部分。
然后要查找缺少该值的记录,请在where子句中测试NULL键。
SELECT *
FROM ddcoe_tbls.ack_flextable ack_flextable1
INNER JOIN ddcoe_tbls.ack_main_config config
ON ack_flextable1.ack_extract_id = config.ack_extract_id
LEFT JOIN ddcoe_tbls.ack_flextable ack_flextable2
ON ack_flextable1.cnst_giftran_key = ack_flextable2.cnst_giftran_key
AND ack_flextable2.ack_extract_id = 8
WHERE ack_flextable2.cnst_giftran_key IS NULL
AND config.ack_extract_file_nm LIKE '%Dtl%'
AND ack_flextable1.ack_extract_id = 9
AND ack_flextable2.cnst_giftran_key IS NULL
答案 1 :(得分:1)
这不是答案,只是一个解释
从你的评论到Joe Stefanelli的回答我收集到你并不完全理解外连接中WHERE和ON的问题。那么让我们来看一个例子。
我们正在寻找所有供应商的最后订单,即订单记录,其中没有供应商的新订单。
select *
from order
where not exists
(
select *
from order newer
where newer.supplier = order.supplier
and newer.orderdate > order.orderdate
);
这是直截了当的;查询与我们刚刚放入单词的内容相匹配:查找不为同一供应商提供新订单的订单。
使用反连接模式的相同查询:
select order.*
from order
left join order newer on newer.supplier = order.supplier
and newer.orderdate > order.orderdate
where newer.id is null;
在这里,我们将所有新订单加入每个订单,因此可能会产生巨大的中间结果。通过左外连接,我们确保在没有供应商的新订单时附加虚拟记录。然后,我们最后使用WHERE子句扫描中间结果,仅保留附加记录的ID为null的记录。好吧,ID显然是表的主键,永远不能为空,所以我们保留的只是外连接结果,其中较新的数据只是一个包含空值的虚拟记录。因此,我们得到了没有新订单的订单。
谈论一个巨大的中间结果:这怎么能比第一个查询更快?好吧,它不应该。实际上,第一个查询应该同样快速或更快地运行。一个好的DBMS将看到这一点并为两个查询制定相同的执行计划。然而,一个相当年轻的DBMS可能真的更快地执行反连接。这是因为开发人员在连接技术方面投入了大量精力,因为在每个查询中都需要这些技术,而且还没有那么关心IN和EXISTS。在这种情况下,可能会遇到NOT IN或NOT EXISTS的性能问题,而是使用反连接模式。
现在关于WHERE / ON问题:
select order.*
from order
left join order newer on newer.orderdate > order.orderdate
where newer.supplier = order.supplier
and newer.id is null;
这与以前几乎相同,但有些标准已从ON移至WHERE。这意味着外连接获得不同的标准。以下是发生的事情:每个订单都能找到所有新订单 - 无论哪个供应商!因此,最后一个订单日期的所有订单都获得了外连接虚拟记录。但是在WHERE子句中,我们删除了供应商不匹配的所有对。请注意,外连接记录对于newer.supplier包含NULL,因此newer.supplier = order.supplier
对它们来说永远不会成立;他们被删除了。但是,如果我们删除所有外连接记录,我们得到的结果与香草内连接完全相同。当我们在WHERE子句中放入外连接标准时,我们将外连接转换为内连接。因此查询可以重写为
select order.*
from order
inner join order newer on newer.orderdate > order.orderdate
where newer.supplier = order.supplier
and newer.id is null;
对于FROM和INNER JOIN中的表,标准是ON还是WHERE并不重要;它取决于可读性,因为这两个标准同样适用。
现在我们看到newer.id is null
永远不会成真。最终结果将为空 - 这正是您的查询所发生的事情。
答案 2 :(得分:0)
您可以尝试使用此查询:
select * from ddcoe_tbls.ack_main_config
where cnst_giftran_key not in
(
select cnst_giftran_key from ddcoe_tbls.ack_main_config
where ack_extract_id = 8
)
and ack_extract_id = 9;