mysql - 将除 1 条匹配多个字段(几乎重复)的记录之外的所有记录标记为已删除
mysql - mark all but 1 records matching multiple fields (near duplicates) as deleted
我有一个 mysql table 用于购物车中的商品。
我需要将相同项目的任何重复项标记为已删除(通过在 'deleted' 列中输入时间戳,而不是出于审计跟踪原因实际删除)。
table(order_item)的列是:
id (int, primary key)
order_id (int)
type (enum)
item_id* (int)
timeslot_id* (int)
price_id* (int)
created (datetime)
deleted (datetime)
我想更新 table 中除 1 项之外的所有重复项目(与另一行具有相同的值),以便为标有 * 的列上的订单更新当前日期时间删除的列。这样一次只能购买一件相同的产品。
我目前通过使用 GROUP BY 和 ID 计数进行 select 查询并使用 Concat 获取以逗号分隔的 ID 列表 - 然后在一个单独的查询。
SELECT COUNT(id) AS c,
GROUP_CONCAT(DISTINCT id SEPARATOR ",") AS ids
FROM cps_order_item WHERE order_id = "10"
AND deleted = "0000-00-00 00:00:00"
GROUP BY type, item_id, timeslot_id, price_id;
有什么可靠的方法可以在一次查询中完成所有这些操作?
我认为您可以通过更新和自连接来实现逻辑:
update order_item oi
inner join (
select order_id, item_id, timeslot_id, price_id, min(id) as id
from order_item
where deleted = '0000-00-00 00:00:00'
group by order_id, item_id, timeslot_id, price_id
) oi1
on oi1.order_id = oi.order_id
and oi1.item_id = oi.item_id
and oi1.timeslot_id = oi.timeslot_id
and oi1.price_id = oi.price_id
and oi1.id <> oi.id
set oi.deleted = now()
where oi.deleted = '0000-00-00 00:00:00'
子查询计算每个值元组的最小值 id
。然后外部查询为在元组上匹配且其 id
不是最小值的行设置列 deleted
。
这一次处理所有订单。您可以在外部查询的 where
子句中添加一个过滤器以仅处理一个订单。如果您愿意,您也可以将聚合函数更改为其他函数(也许您想要 max(id)
而不是 min(id)
)。
注意:此解决方案 不适用于 MySQL。请参阅下面的评论。我留下它希望它可以帮助将来使用其他 RDBMS 的人。
只需删除同一订单中创建日期晚于您正在考虑的订单的商品。我不太确定 MySQL 语法,但看起来像:
UPDATE order_item o
SET deleted = NOW()
WHERE deleted = '0000-00-00 00:00:00'
AND order_id = 10
AND EXISTS (
SELECT *
FROM order_item
WHERE order_id = o.order_id
AND item_id = o.item_id
AND type = o.type
AND timeslot_id = o.timeslot_id
AND price_id = o.price_id
AND deleted = o.deleted
AND created > o.created
);
我使用了与您提供的查询相同的约束条件。
您可能需要删除 AND ORDER = ID
行以一次性清除所有订单。
也许 price_id、type 和 timeslot_id 的约束是不必要的(假设项目 id 暗示了这些属性)。
我有一个 mysql table 用于购物车中的商品。 我需要将相同项目的任何重复项标记为已删除(通过在 'deleted' 列中输入时间戳,而不是出于审计跟踪原因实际删除)。
table(order_item)的列是:
id (int, primary key)
order_id (int)
type (enum)
item_id* (int)
timeslot_id* (int)
price_id* (int)
created (datetime)
deleted (datetime)
我想更新 table 中除 1 项之外的所有重复项目(与另一行具有相同的值),以便为标有 * 的列上的订单更新当前日期时间删除的列。这样一次只能购买一件相同的产品。
我目前通过使用 GROUP BY 和 ID 计数进行 select 查询并使用 Concat 获取以逗号分隔的 ID 列表 - 然后在一个单独的查询。
SELECT COUNT(id) AS c,
GROUP_CONCAT(DISTINCT id SEPARATOR ",") AS ids
FROM cps_order_item WHERE order_id = "10"
AND deleted = "0000-00-00 00:00:00"
GROUP BY type, item_id, timeslot_id, price_id;
有什么可靠的方法可以在一次查询中完成所有这些操作?
我认为您可以通过更新和自连接来实现逻辑:
update order_item oi
inner join (
select order_id, item_id, timeslot_id, price_id, min(id) as id
from order_item
where deleted = '0000-00-00 00:00:00'
group by order_id, item_id, timeslot_id, price_id
) oi1
on oi1.order_id = oi.order_id
and oi1.item_id = oi.item_id
and oi1.timeslot_id = oi.timeslot_id
and oi1.price_id = oi.price_id
and oi1.id <> oi.id
set oi.deleted = now()
where oi.deleted = '0000-00-00 00:00:00'
子查询计算每个值元组的最小值 id
。然后外部查询为在元组上匹配且其 id
不是最小值的行设置列 deleted
。
这一次处理所有订单。您可以在外部查询的 where
子句中添加一个过滤器以仅处理一个订单。如果您愿意,您也可以将聚合函数更改为其他函数(也许您想要 max(id)
而不是 min(id)
)。
注意:此解决方案 不适用于 MySQL。请参阅下面的评论。我留下它希望它可以帮助将来使用其他 RDBMS 的人。
只需删除同一订单中创建日期晚于您正在考虑的订单的商品。我不太确定 MySQL 语法,但看起来像:
UPDATE order_item o
SET deleted = NOW()
WHERE deleted = '0000-00-00 00:00:00'
AND order_id = 10
AND EXISTS (
SELECT *
FROM order_item
WHERE order_id = o.order_id
AND item_id = o.item_id
AND type = o.type
AND timeslot_id = o.timeslot_id
AND price_id = o.price_id
AND deleted = o.deleted
AND created > o.created
);
我使用了与您提供的查询相同的约束条件。
您可能需要删除 AND ORDER = ID
行以一次性清除所有订单。
也许 price_id、type 和 timeslot_id 的约束是不必要的(假设项目 id 暗示了这些属性)。