Teradata

最佳實踐 - 使用派生表還是在連接中使用原始表?

  • December 2, 2015

想像一下,我在 Teradata 中有以下表格:

TableA :  Field1|Field2|Field3
TableB :  Field1|Field4|Field5

我正在嘗試加入這兩個表

方法一:

SEL TableA.Field3, TableB.Field4
FROM TableA 
LEFT JOIN TableB
ON TableA.Field1 = TableB.Field1

WHERE TableB.Field5<>0

方法二:

SEL TableA.Field3, TableB.Field4
FROM TableA 
LEFT JOIN TableB
  ON TableA.Field1 = TableB.Field1
 AND TableB.Field5<>0

方法3:

  SEL TableA.Field3, TableB.Field4
   FROM TableA 
   LEFT JOIN (
               SEL Field1 ,Field4
               FROM TableB
               WHERE Field5<>0
             ) DTable
   ON TableA.Field1 = DTable.Field1

問題:我總是選擇方法 3。但最近我的同事建議這不是最佳編碼實踐,因為它在連接中使用子查詢。有沒有類似聯接的編碼標準?

你的同事是對的。方法 3 的子查詢會浪費計算。因此使用方法 2。

方法 1 和方法 3 不會產生相同的結果。方法一中的WHERE子句在加入表後進行過濾。實際上,它將LEFT JOIN轉換為INNER JOIN.

方法 2 等效於方法 3,因為該AND子句在連接之前對 TableB 執行過濾器(這是派生查詢所做的)。

我創建了一個說明案例的SQLFiddle。完整程式碼如下:

CREATE TABLE TableA(
   Field1 int
 , Field2 varchar(10)
 , Field3 varchar(10)
 );

CREATE TABLE TableB(
   Field1 int
 , Field4 varchar(10)
 , Field5 int);

INSERT INTO TableA
SELECT 0, 'Zero', 'Inner'
UNION ALL
SELECT 1, 'One', 'Inner'
UNION ALL
SELECT 2, 'Two', 'Left';

INSERT INTO TableB
SELECT 0, 'Zero', 0
UNION ALL
SELECT 1, 'One', 1
UNION ALL
SELECT 5, 'Five', 5;

SELECT TableA.Field1
 , TableA.Field2
 , TableA.Field3
 , TableB.Field4
 , TableB.Field5
INTO Method1
FROM TableA
 LEFT JOIN TableB on TableA.Field1 = TableB.Field1
WHERE TableB.Field5 <> 0;

SELECT TableA.Field1
 , TableA.Field2
 , TableA.Field3
 , TableB.Field4
 , TableB.Field5
INTO Method2
FROM TableA
 LEFT JOIN TableB on TableA.Field1 = TableB.Field1
   AND TableB.Field5 <> 0;

SELECT TableA.Field1
 , TableA.Field2
 , TableA.Field3
 , DTable.Field4
 , DTable.Field5
INTO Method3
FROM TableA
 LEFT JOIN (SELECT *
            FROM TableB
            WHERE TableB.Field5 <> 0) DTable
 on TableA.Field1 = DTable.Field1;

SELECT *
FROM Method1;

SELECT *
FROM Method2;

SELECT *
FROM Method3;

Teradata 的優化器很可能會將方法 3 重寫為與方法 2 相同的查詢計劃。方法 1 將導致 INNER JOIN,因為對RIGHT錶的限定不應該在 WHERE 子句中,而是在OUTER JOIN條件的 ON 子句中。如果您要在方法 3 的派生表中放置一個聚合步驟(例如 DISTINCT 或 GROUP BY),您會發現優化器可能會將派生表作為單獨的步驟來滿足,而無需重新編寫計劃。

我建議您為每個查詢執行 EXPLAIN 並比較輸出。

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