2017-09-26 32 views
1

我有一個查詢從表CustomerDetails中選擇客戶,並將其連接到另一個表(CustomerActivity)以獲取最後一次登錄時間,最後將連接保留到另一個表(OpenOrderDetails)中獲得最後的未結訂單(如果適用)。我也有一個很大的WHERE子句來過濾這些數據如果記錄不存在,則加入NULL SQL

客戶在任何時候只能在OpenOrderDetails表中有一條記錄。我的查詢如下所示:

SELECT CD.*, H.LastCustomerLoginTime, OD.OrderFiledDate, OD.OrderCompletedDate 
    FROM CustomerDetails CD 
    LEFT JOIN CustomerActivity H ON H.CustomerID = CD.CustomerID 
    LEFT JOIN OpenOrderDetails OD ON CD.CustomerID = OD.CustomerID 
WHERE CD.OrderStatus IN (1,2,3) 
    AND (CustomerType = 1 or (CustomerType = 3 and CustomerActive IN (1,2))) 
    AND (OD.OrderFiledDate IS NULL OR CD.TimeStamp >= OD.OrderFiledDate) 
    AND (OD.OrderCompletedDate IS NULL OR CD.TimeStamp <= OD.OrderCompletedDate) 

我的問題是,這個查詢僅返回在OpenOrderDetails表中記錄的客戶記錄。如何返回每個客戶,並且OrderFiledDate/OrderCompletedDate(如果存在)以及如果該客戶的記錄不存在於OpenOrderDetails表中,則爲NULL?

+0

從什麼表(或多個):場'customerType'和'CustomerActive'?這是操作問題的常見順序。您希望表格上的過濾器作爲連接的一部分保持連接狀態。如果它們出現在where子句中,那麼LEFT加入就像內連接一樣。從邏輯上說,這些表格已加入。 where子句然後消除不符合標準的值;包括左連接生成的NULLS。對OD進行null檢查是保持左連接值不太常見但可接受的方法,這就是爲什麼我詢問CustomerActive和CustomerType的原因。 – xQbert

+0

*這個問題可能比簡單的where子句限制還要多。我猜想'customerType'或'CustomerActive'中的一個或兩個不在customerDetails中。並且它也需要移入連接或具有空檢查。 – xQbert

+0

第二個左連接上的「DLECS.CustomerID」是什麼?它不應該是OD.CustomerID嗎?定義的查詢中不存在別名/表DLECS。 – xQbert

回答

1

只是將一些OpenOrderDetails條件join條款

SELECT CD.*, H.LastCustomerLoginTime, OD.OrderFiledDate, OD.OrderCompletedDate 
FROM CustomerDetails CD 
LEFT JOIN CustomerActivity H ON H.CustomerID = CD.CustomerID 
LEFT JOIN OpenOrderDetails OD ON CD.CustomerID = DLECS.CustomerID 
        AND (OD.OrderFiledDate IS NULL OR CD.TimeStamp >= OD.OrderFiledDate) 
        AND (OD.OrderCompletedDate IS NULL OR CD.TimeStamp <= OD.OrderCompletedDate) 
WHERE CD.OrderStatus IN (1,2,3) 
AND (CustomerType = 1 or (CustomerType = 3 and CustomerActive IN (1,2))) 
+0

雖然我同意這更容易閱讀/關注。我不明白它會如何改變結果。 OD域的空檢查和OR的使用將保持來自左連接的值。那麼爲什麼這個工作和user1501171不是? – xQbert

+0

要承認我很震驚這個工作,你原來的查詢沒有@ user1501171。我沒有看到DLECS來自哪裏...... – xQbert

1

當做一個LEFT JOIN,引用任何右側表列的WHERE子句將它變成一個INNER JOIN。爲了解決這個問題,只需從WHERE子句中刪除引用「右側」列的所有謂詞並將它們移動到LEFT JOIN條件。

東西沿着這些路線...

SELECT 
    CD.*, 
    H.LastCustomerLoginTime, 
    OD.OrderFiledDate, 
    OD.OrderCompletedDate 
FROM 
    CustomerDetails CD 
    LEFT JOIN CustomerActivity H 
     ON H.CustomerID = CD.CustomerID 
    LEFT JOIN OpenOrderDetails OD 
     ON CD.CustomerID = DLECS.CustomerID 
     AND ( OD.OrderFiledDate IS NULL 
      OR CD.TimeStamp >= OD.OrderFiledDate 
     ) 
     AND ( OD.OrderCompletedDate IS NULL 
       OR CD.TimeStamp <= OD.OrderCompletedDate 
      ) 
WHERE 
    CD.OrderStatus IN (1, 2, 3) 
    AND (
      CustomerType = 1 
      OR 
      ( 
       CustomerType = 3 
       AND CustomerActive IN (1, 2) 
      ) 
     ); 
+0

說明:在執行LEFT JOIN時,引用WHERE子句中的任何右側列表_而不允許NULLs_會將其變爲INNER JOIN。 – HABO

+0

@HABO - 技術上......是的,你是對的......但是沒有必要把想要學習的人與奇怪的語法混爲一談。 –

相關問題