【问题标题】:SQL: Filter data by datetimeSQL:按日期时间过滤数据
【发布时间】:2015-04-07 21:51:01
【问题描述】:

我有一个巨大的表,我正试图在 MS SQL Server Management Studio 中精简。目前每 5 秒有一行数据。我想缩小表格,每 30 分钟只保存 1 行。

例如,而不是有数千行

    Timestamp            A   B   C
    2015-01-01 00:00:00  1   5   6
    2015-01-01 00:00:05  5   7   1
    2015-01-01 00:00:10  2   2   3
    2015-01-01 00:00:15  2   1   0
    ......
    2015-04-10 13:55:55  4   5   6
    2015-04-10 13:56:00  6   4   2

我想把它变薄,所以我只有

    Timestamp            A   B   C
    2015-01-01 00:00:00  1   5   6
    2015-01-01 00:30:00  2   5   7
    2015-01-01 01:00:00  1   7   6
    ......
    2015-04-10 13:30:00  4   5   6
    2015-04-10 14:00:00  6   4   2

谢谢!

【问题讨论】:

  • 澄清一下,您是否希望它每 30 秒快照一次,或者行是否应该包含自前 30 秒以来的所有数据?也就是说,您是要删除时间戳不是 30 秒间隔的所有行,还是要对每个间隔的数据求和(我猜是计数)?
  • 感谢您的澄清!我只想要每 30 分钟一次的快照,这样就不需要其余数据并且可以删除。
  • 最后一个数字(在秒上)是否总是 0 或 5,或者是否有可能在小时后 3 秒有数据?

标签: sql sql-server datetime


【解决方案1】:

鉴于您的样本数据,您可以这样做:

select t.*
from table t
where datepart(minute, timestamp) in (0, 30) and
      datepart(second, timestamp) = 0;

【讨论】:

  • 如果任务是瘦桌子,那么delete from t where not (datepart(second, timestamp) in (0, 30) and datepart(second, timestamp) = 0);
  • 每个好的删除语句都应该从一个选择语句开始。
【解决方案2】:

delete from [massive Table] where datepart(mi,timestamp) not in (0,30)

将删除所有与您的条件不匹配的行。

【讨论】:

    【解决方案3】:

    如果你的时间并不总是在 0 或 5 内,你可以试试这个。

    Delete
    From    YourTable
    Where   DateDiff(Second, '20000101', TimeStamp) % 1800 > 4
    

    这通过计算自 2000 年 1 月 1 日以来过期的秒数来工作。mod 运算符用于计算您想要保留的时间间隔。 30分钟有1800秒。因此,应删除秒数大于 4 的任何内容。基本上,我们不是以小时、分钟和秒来考虑时间,而是以 1800 秒的间隔来考虑时间,这正是您想要的。

    【讨论】:

      【解决方案4】:

      从一组行中选择一行时,编写依赖于可能不正确的假设的代码并不总是一个好主意。例如,在整点半小时查找第一个条目时,是否保证始终存在时间戳为“hh-00-00”和“hh-30-00”的条目?您的示例数据表明了这一点,但这是否准确地代表了您的实际数据?

      您可能想说的是,您希望保留“每个小时和半小时边界后的第一个条目”。这样一来,您就知道每半小时间隔会有一个条目,即使第一个条目是在一小时后两秒或半小时后进入的。

      所以第一步是将日期分成半小时组。我发现这样做的最好方法是

      Convert( SmallDatetime, Floor( Cast( Timestamp AS float ) * 48.0 ) / 48.0 )
      

      将其添加到查询列表的末尾并查看时间是否正确(向下舍入到正好是整点或整点半小时)。特别注意非常接近(之前和之后)边界的时间。

      使用它,很容易生成在每个半小时增量内最先出现的时间列表。您不必担心每个增量都有一个将半小时边界与秒相匹配的条目。加入它,您将获得要保留的完整行列表。删除所有其余部分。

      with
      Halfs( HalfHour )as(
          select  Min( Timestamp )
          from    TData
          group by Convert( SmallDatetime, Floor( Cast( Timestamp AS float ) * 48.0 ) / 48.0 )
      )
      select  t.*
      from    TData t
      join    Halfs h
          on  h.HalfHour = t.TimeStamp;
      

      http://sqlfiddle.com/#!6/65a5c/1/0

      【讨论】:

        【解决方案5】:

        这是一个可能有帮助的例子:

        CREATE TABLE [dbo].[Position](
        [PositionId] [int] IDENTITY(1,1)  PRIMARY KEY,
        [Latitude] [float] NOT NULL,
        [Longitude] [float] NOT NULL,
        [Date] [datetime] NOT NULL,
        [DeviceId] [int] NOT NULL
        )
        
        insert into Position Values
        (51.46,-2.58,'2022-01-04 08:05:00',1),
        (51.41,-2.53,'2022-01-04 08:25:00',1),
        (51.39,-2.48,'2022-01-04 08:45:00',1),
        (51.39,-2.45,'2022-01-04 08:50:00',1),
        (51.38,-2.37,'2022-01-04 09:10:00',1),
        (51.41,-2.52,'2022-01-04 09:30:00',1),
        (51.44,-2.56,'2022-01-04 09:50:00',1),
        (51.45,-2.57,'2022-01-04 10:20:00',1),
        (51.46,-2.58,'2022-01-04 11:40:00',1)
        
        Declare @IntervalHours int = 1
        Declare @Start Datetime = '2022-01-04 07:00'
        Declare @End Datetime = '2022-01-04 12:00'
        Declare @DeviceId int = 1
        
        SELECT PositionId, [Date], RoundedDate, Latitude, Longitude, DeviceId
        FROM (SELECT 
                PositionId, 
                Latitude, 
                Longitude,
                [Date],
                DATEADD(hour, DATEDIFF(hour, 0, [Date]), 0) AS RoundedDate, 
                DeviceId,
                ROW_NUMBER() OVER (PARTITION BY (DATEDIFF(hour, 0, [Date])/@IntervalHours) ORDER BY [Date] ASC) AS row_index
            From Position
            WHERE Date BETWEEN @Start AND @End and DeviceId = @DeviceId
            GROUP BY [Date], PositionId, Latitude,Longitude,DeviceId
            ) as grouped
        where grouped.row_index = 1
        

        【讨论】:

          猜你喜欢
          • 2021-09-01
          • 1970-01-01
          • 2013-10-20
          • 1970-01-01
          • 1970-01-01
          • 2021-12-27
          • 1970-01-01
          • 2022-09-23
          • 1970-01-01
          相关资源
          最近更新 更多