我有以下数据,它们增长得太快太快了:
c1 c2 timestamp
5 1 2019-01-31 15:35:36.055000
6 2 2019-01-31 15:35:36.055000
7 3 2019-01-31 15:35:35.055000
8 4 2019-01-31 15:35:35.055000
7 3 2019-01-30 15:35:36.055000
8 4 2019-01-30 15:35:36.055000
7 3 2019-01-30 15:35:35.055000
8 4 2019-01-30 15:35:35.055000
我想通过将时间戳上限设置为10秒钟来替换表的一部分,其中时间戳早于2019-01-31 00:00:00:000000 结果应该是这样,并且上述表中的底部两列不应在新表中:
c1 c2 timestamp
5 1 2019-01-31 15:35:36.055000
6 2 2019-01-31 15:35:36.055000
7 3 2019-01-31 15:35:35.055000
8 4 2019-01-31 15:35:35.055000
7 3 2019-01-30 15:35:40.000000
8 4 2019-01-30 15:35:40.000000
我执行了以下查询以取消时间戳记,但是我不知道如何替换表的特定部分。
SELECT c1, c2, FROM_UNIXTIME(CEIL(UNIX_TIMESTAMP(timestamp) / 10) * 10) as datetime
FROM mytable
WHERE timestamp in (SELECT MAX(timestamp) FROM mytable
GROUP BY FROM_UNIXTIME(CEIL(UNIX_TIMESTAMP(timestamp) / 10) * 10))
GROUP BY datetime
答案 0 :(得分:1)
像这样的查询将列出所有行的时间戳值
UPDATE mytable SET timestamp=FROM_UNIXTIME(CEIL(UNIX_TIMESTAMP(timestamp) / 10) * 10);
如果只想将其应用于某些行,请添加WHERE提示
答案 1 :(得分:1)
(注意:如果c1或c2可以为null,则在不进行重大修改的情况下,该解决方案可能对您不起作用。)
如果您只想保留每10秒一次的最新时间,则应执行以下操作:
DELETE
FROM mytable
WHERE timestamp < '2019-01-31 00:00:00:000000'
AND (c1, c2, timestamp)
NOT IN (
SELECT ends.c1, ends.c2, ends.windowEnd
FROM ( SELECT c1, c2
, FROM_UNIXTIME(CEIL(UNIX_TIMESTAMP(timestamp) / 10) * 10) as dtWindow
, MAX(timestamp) AS windowEnd
FROM mytable
WHERE timestamp < '2019-01-31 00:00:00:000000'
GROUP BY c1, c2, dtWindow
) AS ends
)
;
注意:有时MySQL对于从同一查询中要从中删除的表中进行选择有些挑剔,但是我认为该子查询中的间接层级别足够高,这不应该成为问题。
奖金:如果要在运行此类查询之前仔细检查将要删除的记录,可以将子选择移到联接选择中以预览内容。
SELECT t.*
, CASE WHEN ends.rowPresent IS NOT NULL THEN 'keep' ELSE 'to delete' END AS `plan`
FROM mytable AS t
LEFT JOIN (
SELECT c1, c2
, FROM_UNIXTIME(CEIL(UNIX_TIMESTAMP(timestamp) / 10) * 10) as dtWindow
, MAX(timestamp) AS windowEnd
, 1 AS rowPresent -- You could just use c1 or c2 in the above CASE, but if they could naturally be null that would complicate things
FROM mytable
WHERE timestamp < '2019-01-31 00:00:00:000000'
GROUP BY c1, c2, dtWindow
) AS ends ON t.c1 = ends.c1 AND t.c2 = ends.c2 AND t.timestamp = ends.windowEnd
WHERE t.timestamp < '2019-01-31 00:00:00:000000'
;