[英]LEFT JOIN WHERE RIGHT IS NULL for same table in Teradata SQL
我有一張有51條記錄的表。 表結構如下所示:
ack_extract_id query_id cnst_giftran_key field1 value1
現在ack_extract_ids可以為8,9。 我想檢查是否存在extractran_id 9而不是8中的giftran鍵。
我試過的是
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的記錄,對嗎?
我在這里想念什么?
當您在where子句(在您的情況下為ack_flextable2.ack_extract_id
中測試來自左聯接表的列時,您將強制該ack_flextable2.ack_extract_id
表現為內部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
這沒有答案,只是一種解釋
從您的評論到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;
這看起來幾乎與以前相同,但是某些條件已從“開”移到“位置”。 這意味着外部聯接獲得不同的條件。 這就是發生的情況:對於每個訂單,查找所有較新的訂單-不管是哪個供應商! 因此,最后一個訂單日期的所有訂單都將獲得外部聯接虛擬記錄。 但是,在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
永遠不會為真。 最終結果將為空-這正是查詢所發生的情況。
您可以嘗試使用以下查詢:
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;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.