如何删除 mysql 中的行,其中特定字段按时间顺序在另一个重复项旁边重复
How do I delete rows in mysql where a specific field is duplicated chronologically next to the other duplication
前言
我知道这里已经有许多 'delete duplicate row' 解决方案,但我觉得我的查询有很大差异,足以保证提出一个新问题。
背景
我的 table 作为所有产品价格点的历史档案,加班,按国家。它将无限期地保留历史数据。
我每天有一个 'price' 提要,其中包含 7 天的产品价格历史记录和 7 天的未来产品价格。数据包含 'country'、'product code' (sku)、'price' 和 'date from' 日期的价格。没有'date to';相关价格(在给定的一天)来自 'date from' 字段。
每天都会有很多重复的东西;由于大多数相同的数据日复一日地发送,并且给定的产品价格可能出现多达 14 次;因为它在 14 天内每天发送一次。我用 'sku_country_date_index' ('sku', 'country', 'date_from') 的 UNIQUE KEY 克服了这个问题——这可以防止这些类型的重复。
但是,发送系统并不是特别智能,并且经常发送价格变化数据,即使价格在上次记录的日期已经是那个价格,例如“2015-01-01 @ 10 英镑”,“2015-01-03 @ 10 英镑”。我想删除这些不必要的价格行。
此处发布的其他解决方案提供了有关删除完全重复行的信息;例如删除所有行,第一条,其中产品 X 的价格重复 - 这不是 suitable,因为价格会随着时间的推移而上下波动,并且可能在以后的日期具有相同的价格(价格之间的变化)。
问题
如何删除 mysql 中特定字段按时间顺序与另一个重复项相邻的行。
设置
Table:
CREATE TABLE IF NOT EXISTS `price` (
`import_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`country` varchar(2) COLLATE utf8_bin DEFAULT NULL,
`sku` varchar(7) COLLATE utf8_bin DEFAULT NULL,
`date_from` date DEFAULT NULL,
`price` decimal(10,2) DEFAULT NULL,
PRIMARY KEY (`import_id`),
UNIQUE KEY `sku_country_date_index` (`sku`,`country`,`date_from`),
KEY `sku_index` (`sku`),
KEY `country_index` (`country`),
KEY `date_from_index` (`date_from`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=1;
示例数据:
REPLACE INTO `price`
(`country`, `sku`, `price`, `date_from`)
VALUES
('uk', '123', '10.00', '2015-01-01'),
('uk', '123', '11.00', '2015-01-04'),
('uk', '123', '9.00', '2015-01-06'),
('uk', '123', '9.00', '2015-01-09'),
('uk', '123', '9.00', '2015-01-13'),
('uk', '123', '10.00', '2015-01-16'),
('uk', '123', '9.00', '2015-01-20'),
('uk', '123', '10.00', '2015-01-25'),
('uk', '124', '10.00', '2015-01-06'),
('uk', '125', '10.00', '2015-01-06'),
('ie', '123', '10.00', '2015-01-06'),
('ie', '123', '14.00', '2015-01-07'),
('ie', '125', '10.00', '2015-01-06')
要求:
删除以下两行,因为它们不需要确定给定日期的产品价格 -
('uk', '123', '9.00', '2015-01-09'),
('uk', '123', '9.00', '2015-01-13'),
解决方案可以是 CREATE 或 REPLACE 语句的一部分 - 甚至是后续的 DELETE。
我的方法
供参考;以下是我采取的方法;不幸的是删除了太多行。它没有考虑如果中间有其他价格,则价格可以重复。
DELETE FROM `price` WHERE `import_id` IN (
SELECT t1.import_id
FROM `price` t1, `price` t2
WHERE 1
AND t1.date_from > t2.date_from
AND t1.sku = t2.sku
AND t1.price = t2.price
AND t1.country = t2.country
)
因此,如果我没理解错的话,您希望在给定国家/地区、sku 和价格相同的一组记录的情况下,保留最低 import_id 的一行。
我认为这会成功(警告,未经测试):
DELETE p2.*
FROM price p1
INNER JOIN price p2
ON p2.country = p1.country
AND p2.sku = p1.sku
AND p2.price = p1.price
AND p2.import_id > p1.import_id;
delete d
from t1 d
join t1 dd
on d.import_id = dd.import_id + 1
and d.sku = dd.sku
and d.price = dd.price
and d.country = dd.country
如果table未排序,我们可以使用上述解决方案中的想法来接收不需要的import_id
集
set @n:=0;
set @m:=0;
delete
from t1
where t1.import_id in (
select d.import_id
from
(select @n:=@n+1 AS row_number, import_id, country, sku, price, date_from
from t1 order by country, date_from) as d
join
(select @m:=@m+1 AS row_number, import_id,country, sku, price, date_from
from t1 order by country, date_from) as dd
on d.row_number = dd.row_number + 1
and d.sku = dd.sku
and d.price = dd.price
and d.country = dd.country)
前言
我知道这里已经有许多 'delete duplicate row' 解决方案,但我觉得我的查询有很大差异,足以保证提出一个新问题。
背景
我的 table 作为所有产品价格点的历史档案,加班,按国家。它将无限期地保留历史数据。
我每天有一个 'price' 提要,其中包含 7 天的产品价格历史记录和 7 天的未来产品价格。数据包含 'country'、'product code' (sku)、'price' 和 'date from' 日期的价格。没有'date to';相关价格(在给定的一天)来自 'date from' 字段。
每天都会有很多重复的东西;由于大多数相同的数据日复一日地发送,并且给定的产品价格可能出现多达 14 次;因为它在 14 天内每天发送一次。我用 'sku_country_date_index' ('sku', 'country', 'date_from') 的 UNIQUE KEY 克服了这个问题——这可以防止这些类型的重复。
但是,发送系统并不是特别智能,并且经常发送价格变化数据,即使价格在上次记录的日期已经是那个价格,例如“2015-01-01 @ 10 英镑”,“2015-01-03 @ 10 英镑”。我想删除这些不必要的价格行。
此处发布的其他解决方案提供了有关删除完全重复行的信息;例如删除所有行,第一条,其中产品 X 的价格重复 - 这不是 suitable,因为价格会随着时间的推移而上下波动,并且可能在以后的日期具有相同的价格(价格之间的变化)。
问题
如何删除 mysql 中特定字段按时间顺序与另一个重复项相邻的行。
设置
Table:
CREATE TABLE IF NOT EXISTS `price` (
`import_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`country` varchar(2) COLLATE utf8_bin DEFAULT NULL,
`sku` varchar(7) COLLATE utf8_bin DEFAULT NULL,
`date_from` date DEFAULT NULL,
`price` decimal(10,2) DEFAULT NULL,
PRIMARY KEY (`import_id`),
UNIQUE KEY `sku_country_date_index` (`sku`,`country`,`date_from`),
KEY `sku_index` (`sku`),
KEY `country_index` (`country`),
KEY `date_from_index` (`date_from`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=1;
示例数据:
REPLACE INTO `price`
(`country`, `sku`, `price`, `date_from`)
VALUES
('uk', '123', '10.00', '2015-01-01'),
('uk', '123', '11.00', '2015-01-04'),
('uk', '123', '9.00', '2015-01-06'),
('uk', '123', '9.00', '2015-01-09'),
('uk', '123', '9.00', '2015-01-13'),
('uk', '123', '10.00', '2015-01-16'),
('uk', '123', '9.00', '2015-01-20'),
('uk', '123', '10.00', '2015-01-25'),
('uk', '124', '10.00', '2015-01-06'),
('uk', '125', '10.00', '2015-01-06'),
('ie', '123', '10.00', '2015-01-06'),
('ie', '123', '14.00', '2015-01-07'),
('ie', '125', '10.00', '2015-01-06')
要求:
删除以下两行,因为它们不需要确定给定日期的产品价格 -
('uk', '123', '9.00', '2015-01-09'),
('uk', '123', '9.00', '2015-01-13'),
解决方案可以是 CREATE 或 REPLACE 语句的一部分 - 甚至是后续的 DELETE。
我的方法
供参考;以下是我采取的方法;不幸的是删除了太多行。它没有考虑如果中间有其他价格,则价格可以重复。
DELETE FROM `price` WHERE `import_id` IN (
SELECT t1.import_id
FROM `price` t1, `price` t2
WHERE 1
AND t1.date_from > t2.date_from
AND t1.sku = t2.sku
AND t1.price = t2.price
AND t1.country = t2.country
)
因此,如果我没理解错的话,您希望在给定国家/地区、sku 和价格相同的一组记录的情况下,保留最低 import_id 的一行。
我认为这会成功(警告,未经测试):
DELETE p2.*
FROM price p1
INNER JOIN price p2
ON p2.country = p1.country
AND p2.sku = p1.sku
AND p2.price = p1.price
AND p2.import_id > p1.import_id;
delete d
from t1 d
join t1 dd
on d.import_id = dd.import_id + 1
and d.sku = dd.sku
and d.price = dd.price
and d.country = dd.country
如果table未排序,我们可以使用上述解决方案中的想法来接收不需要的import_id
集set @n:=0;
set @m:=0;
delete
from t1
where t1.import_id in (
select d.import_id
from
(select @n:=@n+1 AS row_number, import_id, country, sku, price, date_from
from t1 order by country, date_from) as d
join
(select @m:=@m+1 AS row_number, import_id,country, sku, price, date_from
from t1 order by country, date_from) as dd
on d.row_number = dd.row_number + 1
and d.sku = dd.sku
and d.price = dd.price
and d.country = dd.country)