【问题标题】:Delete all rows except max(timestamp) on each day in mysql在mysql中的每一天删除除max(timestamp)之外的所有行
【发布时间】:2019-01-03 10:24:03
【问题描述】:

如何删除每天除每种货币的最大(时间戳)之外的所有行。因此,查询必须每天只保留每种货币的最新行。

数据

Id,currency,value,timestamp
21,btc,8000,2018-07-25 23:00:00 --> Keep this row
20,eth, 800,2018-07-25 23:00:00 --> Keep this row
19,btc,7999,2018-07-25 22:00:00
18,eth, 799,2018-07-25 22:00:00
17,btc,7998,2018-07-25 21:00:00
16,eth, 798,2018-07-25 21:00:00
15,btc,7997,2018-07-24 23:00:00 --> Keep this row
14,eth, 800,2018-07-24 23:00:00 --> Keep this row
13,btc,7996,2018-07-24 22:00:00
12,eth, 799,2018-07-24 22:00:00
11,btc,7995,2018-07-24 21:00:00
10,eth, 798,2018-07-24 21:00:00

每种货币每天的最新 (max(created_at)) 行

SELECT
  t.currency
 , DATE(t.created_at)
 , MAX(t.created_at)

FROM `tbltest` t

GROUP BY 
   t.currency
 , DATE(t.created_at)

我可以找到每种货币每天最新的 (max(created_at)) 行,但我如何只保留这些行,而删除所有其他行?

解决方案

由于最高的时间戳也有最高的 id,所以使用的简单解决方案如下:

DELETE FROM `tbltest` 
WHERE id NOT IN 
    (SELECT MAX(id) 
       FROM (select * FROM `tbltest`) as t2 
   GROUP BY currency, DATE(created_at))

【问题讨论】:

  • DELETE DROM tablename WHERE NOT IN([your max query])

标签: mysql sql


【解决方案1】:

返回不删除行的子查询会对您有所帮助:

DELETE FROM table_test
WHERE Id <> (SELECT last.id 
             FROM table_test last
             WHERE cast(last.created_at as date) = cast(table_test.created_at as date)
             ORDER BY last.created_at DESC
             LIMIT 1)

【讨论】:

  • SELECT TOP 1 ... 不是 MySQL 语法。你的意思是SELECT ... LIMIT 1
  • @Kaii 好的,谢谢,我会更新的。他昨天把它标记为 SQL Server。
【解决方案2】:

一种方法是选择每种货币和日期的最大时间戳并将其排除在删除之外:

delete from tbltest
where (currency, created_at) not in
(
  select currency, max(created_at)
  from (select * from tbltest) t
  group by currency, date(created_at)
);

我认为这非常易读,在我看来,这在编写 SQL 时很重要。

线

from (select * from tbltest) t

诚然很奇怪。这是因为 MySQL 拒绝您直接查询同一个表的更新。在其他 DBMS 中,您只需编写 from tbltest

如果你更喜欢它,你可以改变

where (currency, created_at) not in
(
  select currency, max(created_at)

where (currency, date(created_at), created_at) not in
(
  select currency, date(created_at), max(created_at)

当然也做同样的事情。选择您认为更易读/更直观的版本。

【讨论】:

    【解决方案3】:

    时间戳最高的行似乎也有最高的 ID。

    DELETE FROM YourTable
    WHERE Id NOT IN (SELECT MAX(Id) FROM YourTable GROUP BY currency, DATE(timestamp))
    

    【讨论】:

      【解决方案4】:

      可以使用下面的sql语句

      Delete from tbltest
      Where t.currency <>
      (
        Select temp.currency
        From
        (
          SELECT Top 1 t.currency, DATE(t.created_at), MAX(t.created_at)
          FROM `tbltest` t
          GROUP BY t.currency, DATE(t.created_at)
          order by (max(created_at)) desc
        )temp
      )
      

      让我知道它是否有效! :)

      【讨论】:

        【解决方案5】:

        您可以使用 rownumber 来解决问题。像这样:

        WITH CTE AS
        (
          SELECT Currency,
                 Timestamp,
                 ROW_NUMBER() OVER (PARTITION BY Currency ORDER BY TIMESTAMP DESC) AS RowNumb
          FROM Table
        )  
        
        DELETE FROM CTE WHERE RowNumb > 1
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-12-15
          • 1970-01-01
          • 1970-01-01
          • 2011-06-08
          • 1970-01-01
          相关资源
          最近更新 更多