2016-12-16 138 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` 
)