2016-12-16 141 views
1

我有這個問題,現在一直在殺我幾天。基於多個不同列的MYSQL刪除

所以我們有一個所有處理訂單的表。 我們有一張所有進入訂單的表格。

我們需要有效地交叉引用新表格中的訂單,該表格不斷更新,以便完全在主表格中完成訂單,以便我們不必完成相同的訂單多次。

我們得到了一批新的訂單後,這是我目前在試圖越過與完成的訂單的表引用它運行查詢:

$sql = "DELETE 
FROM 
    `orders_new` 
WHERE 
    `order` IN (
     SELECT DISTINCT 
      `order` 
     FROM 
      `orders_all` 
    ) 
AND `name` IN (
    SELECT DISTINCT 
     `name` 
    FROM 
     `orders_all` 
) 
AND `jurisdiction` IN (
    SELECT DISTINCT 
     `jurisdiction` 
    FROM 
     `orders_all` 
)"; 

正如你可能會說,我想從「orders_new」表中刪除行,其中在「orders_all」表中已存在具有相同order,namejurisdiction的行。

這是處理這種查詢的正確方法嗎?

+0

訂單字段中的內容是什麼?它是一個ID或產品名稱或產品代碼? –

+0

這是一個訂單ID,由客戶/客戶提供,我們無法更改。 – Justin

回答

1

那麼,正確的方式取決於許多因素。但首先,我不喜歡你的分成兩個表格。在那種情況下,我會引入一個列標識狀態,它會引用一個可能的狀態表。這些將是「新」,「正在進行」,「已完成」。這樣你就可以將一個訂單存儲爲只有一個記錄。 但是你的查詢遷移沒問題,但你應該檢查性能。 看看:https://sqlperformance.com/2012/12/t-sql-queries/left-anti-semi-join 不完全是你的情況,但非常相似。

另一件事:爲什麼你使用DISTINCT。這意味着「訂單」不是唯一的標識符。

根據您的編輯,您可以使用複合關鍵字「訂單」,「名稱」,「管轄權」來確定訂單。這真的是關鍵,整個關鍵,只有關鍵幫助你Codd。如果沒有,你可以刪除一堆記錄。但即使如此,您的查詢也會刪除所有訂單,其中的訂單,名稱和管轄權可以按照不同記錄的表格順序找到。所以你的查詢是錯誤的。

話說,查詢的變體可能是

DELETE order_new 
FROM 
    order_new 
    INNER JOIN 
    order_all ON order_all.order = order_new.order 
        AND order_all.name = order_new.name 
        AND order_all.jurisdiction = order_new.jurisdiction 

但是,真正的問題是你的ER模型。

+0

他的查詢很可能不太好;但我第二感覺這兩個表是這個方向已經走錯了。 – Uueerdo

+0

「訂單」不是一個唯一的標識符,但它們是由客戶提供給我們的,所以我們沒有發言權。 – Justin

+0

@justin在這種情況下,您應該引入srrogate鍵。但是......即使是客戶也應該有辦法唯一地識別訂單。 – 2016-12-16 19:21:53

0

你應該將其轉換成一個DELETE - JOIN構建像

DELETE `orders_new` 
FROM `orders_new` 
INNER JOIN `orders_all` ON `orders_new`.`order` = `orders_all`.`order` 
AND `orders_new`.`name` = `orders_all`.`name` 
AND `orders_new`.`jurisdiction` = `orders_all`.`jurisdiction`; 
+1

因爲我們想要刪除所有三列匹配值的行,所以這些應該不是「AND」條件而不是「OR」? – Justin

+0

@Justin,是的絕對......錯過了那個點 – Rahul

0

不,你的查詢將刪除所有記錄,其中有與同ordernamejurisdiction,任何記錄即使這些記錄是由不同另一個。換句話說,如果order_all中的一行具有相同的order,另一個具有相同的name,並且第三個具有相同的jurisdiction,則orders_new中的一行將被刪除。你很可能會刪除比你想要的更多的方式。取而代之的是,這將是比較合適的:

DELETE FROM `orders_new` 
WHERE (`order`, `name`, jurisdiction`) IN (
    SELECT `order`, `name`, `jurisdiction` 
    FROM `orders_all` 
) 

也許

DELETE FROM `orders_new` 
WHERE EXISTS (
    SELECT 1 
    FROM `orders_all` AS oa 
    WHERE oa.`order` = `orders_new`.`order` 
    AND oa.`name` = `orders_new`.`name` 
    AND oa.`jurisdiction` = `orders_new`.`jurisdiction` 
)