Join

如果存在 col1 上的 SQL 連接,則使用 col2

  • September 3, 2020

有兩個表 T1(col1) 和 T2(col1, col2) 需要連接。但是 T2 可能將 col1 設置為 null,在這種情況下 col2 可以用作備份。

我想要的是加入T1.col1 = T2.col1或者T1.col1 = T2.col2如果 col1 在 T2 中為 NULL。

我已經嘗試過這些:

select * from T2 left join T1
on T1.col1 = coalesce(T2.col1, T2.col2)
select * from T2 left join T1
on T1.col1 in (T2.col1, T2.col2)
select * from T2 left join T1
on T1.col1 = T2.col1
or T1.col1 = T2.col2)

這導致 ETL 工作永無止境。

附加資訊:

  • 紅移數據庫
  • 沒有索引,因為柱狀數據庫
  • T2.col1 和 T2.col2 將同上。T2.col1 來自上游,而 T2.col2 來自 ETL。在上游質量提高之前,我們需要在 col2 上進行回退。

這裡的問題是,使用函式或or圍繞您的連接謂詞意味著數據庫引擎不能使用您可能在相關列上定義的任何索引進行搜尋,因此它被迫進行表掃描。在一張大桌子上,這可能需要很長時間。更糟糕的是,如果這是更大查詢的一部分,您可能會發現必須多次掃描。

如果您在 T2.col1 和 T2.col2(和 T1.col1)上有有用的索引,那麼假設您真正想要的是INNER JOIN

-- find matches for col1
SELECT *
FROM T1
JOIN T2 ON T1.col1 = T2.col1
-- join these results together
UNION ALL
-- find matches for col2 except where will have already matched col1
SELECT *
FROM T1
JOIN T2 ON T1.col1 = T2.col2 AND T2.col1 IS NULL

因為每個UNIONedSELECT都可以避免表掃描,這將比單個更有效SELECT假設存在適當的索引供它們使用。

如果您確實想要一個LEFT JOIN(即您想要包含 T1 中與 T2 中的行完全不匹配的行),那麼您需要一個額外的子句:

-- find matches for col1
SELECT *
 FROM T1
 JOIN T2 ON T1.col1 = T2.col1
-- join these results together
UNION ALL
-- find matches for col2 except where will have already matched col1
SELECT *
 FROM T1
 JOIN T2 ON T1.col1 = T2.col2 
         AND T2.col1 IS NULL -- this will match above and you'll get a duplicate
UNION ALL
-- find rows in T1 where there is no match in T2
SELECT *
 FROM T1
 LEFT JOIN 
      T2 ON T1.col1 = T2.col2 
WHERE T2.col1 IS NULL
  AND NOT EXISTS (SELECT * FROM T2 WHERE T2.col2 = t1.col1)

如果您沒有使用SELECT *(即有一個固定的列列表而不是萬用字元 *),那麼您可能會發現第三個子句更容易理解為:

  SELECT [columns-to-project]
 FROM T1
WHERE NOT EXISTS (SELECT * FROM T2 WHERE T2.col1 = t1.col1)
  AND NOT EXISTS (SELECT * FROM T2 WHERE T2.col2 = t1.col1)

(這是否效率更高或更低,或完全相同,取決於您的數據庫的查詢計劃器和您定義的索引)。

請注意,第一個SELECTs 假設您在 T2 中沒有col2匹配的行T1.col1 = T2.col2col1匹配的行T1.col1 = T2.col1,並且沒有匹配有效T2.col2T2.col1不匹配的行T1.col1。如果確實存在這樣的行,則需要額外的工作,我沒有包括在內,因為您目前的查詢會像我的範例一樣跳過這些匹配項。

另請注意,上述範例的任何效率聲明都依賴於現有的適當索引。

要獲得更具體的答案,您需要編輯您的問題以提供:

  • 表結構,特別是定義了哪些索引。
  • 更詳細的數據描述,特別是關於 T2.col1 和 T2.col2 中的內容和時間。
  • 除非您特別需要與數據庫無關的答案,否則您正在使用什麼數據庫系統(數據庫中可能有特定功能可以幫助進行這種查詢和表設計)。

我會通過在 T2 上編寫一個選擇 col1 或 col2 的 SELECT 語句來解決這個問題,例如:

SELECT  col_to_join = coalesce(col1, col2)
FROM    T2

然後在連接中使用這個 SELECT 語句。

引用自:https://dba.stackexchange.com/questions/274807