6

我有一个大表,每秒钟创建一次记录,并且只想选择过去 2 个月在每小时顶部创建的那些记录。因此,我们将在过去 60 天内每天获得 24 条选定记录

表结构为Dateandtime、Value1、Value2等

非常感谢

4

6 回答 6

3

您可以group by在日期部分 ( cast(col1 as date)) 和小时部分 ( datepart(hh, col1)。然后选择每个小时的最小日期,并对其进行过滤:

select  *
from    YourTable yt
join    (
        select  min(dateandtime) as dt
        from    YourTable
        where   datediff(day, dateandtime, getdate()) <= 60
        group by
                cast(dateandtime as date)
        ,       datepart(hh, dateandtime)
        ) filter
on      filter.dt = yt.dateandtime

或者,您可以按仅包含日期和小时的日期格式进行分组。例如,convert(varchar(13), getdate(), 120)返回2013-05-11 18.

        ...
        group by
                convert(varchar(13), getdate(), 120)
        ) filter
        ...
于 2013-05-11T16:28:18.773 回答
2

为了清楚起见,我可能会使用基于 CTE 的两步方法(这适用于 SQL Server 2005及更高版本 - 您没有明确指定您使用的 SQL Server版本,所以我只是希望您'不再使用像 2000 这样的古老版本):

-- define a "base" CTE to get the hour component of your "DateAndTime" 
-- column and make it accessible under its own name
;WITH BaseCTE AS
(
    SELECT  
        ID, DateAndTime,
        Value1, Value2, 
        HourPart = DATEPART(HOUR, DateAndTime)
    FROM dbo.YourTable
    WHERE DateAndTime >= @SomeThresholdDateHere
), 
-- define a second CTE which "partitions" the data by this "HourPart",
-- and number all rows for each partition starting at 1. So each "last"
-- event for each hour is the one with the RN = 1 value
HourlyCTE AS 
(
    SELECT ID, DateAndTime, Value1, Value2, 
        RN = ROW_NUMBER() OVER(PARTITION BY HourPart ORDER BY DateAndTime DESC)
    FROM BaseCTE
)
SELECT *
FROM HourlyCTE
WHERE RN=1

另外:我不确定您所说的“小时的顶部”到底是什么意思-在每个小时开始时创建的行(例如 at 04:00:00)-或者更确切地说是在该小时的时间跨度中创建的最后一行?如果您的意思是每小时的第一个 - 那么您需要ORDER BY DateAndTime DESCORDER BY DateAndTime ASC

于 2013-05-11T16:37:54.517 回答
2

您可以将选项与 EXISTS 运算符一起使用

SELECT *
FROM dbo.tableName t 
WHERE t.DateAndTime >= @YourDateCondition
  AND EXISTS (
              SELECT 1
              FROM dbo.tableName t2
              WHERE t2.Dateandtime >= DATEADD(HOUR, DATEDIFF(HOUR, 0, t.Dateandtime), 0)
                      AND t2.Dateandtime < DATEADD(HOUR, DATEDIFF(HOUR, 0, t.Dateandtime)+1, 0)
              HAVING MAX(t2.Dateandtime) = t.Dateandtime
              )

带有 CROSS APPLY运算符的 OR 选项

SELECT *
FROM dbo.test83 t CROSS APPLY (
                               SELECT 1
                               FROM dbo.test83 t2
                               WHERE t2.Dateandtime >= DATEADD(HOUR, DATEDIFF(HOUR, 0, t.Dateandtime), 0)
                                     AND t2.Dateandtime < DATEADD(HOUR, DATEDIFF(HOUR, 0, t.Dateandtime)+1, 0)
                               HAVING  MAX(t2.Dateandtime) = t.Dateandtime                            
                               ) o(IsMatch)
WHERE t.DateAndTime >= @YourDateCondition 

为了提高性能,请使用此索引:

CREATE INDEX x ON dbo.test83(DateAndTime) INCLUDE(Value1, Value2)
于 2013-05-11T21:42:33.860 回答
1

您可以为此使用窗口函数:

select dateandtime, val1, val2, . . .
from (select t.*,
             row_number() over (partition by cast(dateandtime as date), hour(dateandtime)
                                order by dateandtime
                               ) as seqnum
      from t
     ) t
where seqnum = 1

该函数为子句row_number()定义的每个组分配一个序号partition——在本例中为每天的每个小时。在这个组中,它按dateandtime值排序,因此最接近小时的顶部的值是 1。外部查询只为每个组选择这一记录。

您可能需要一个额外的过滤器子句来获取过去 60 天的记录。在子查询中使用它:

where dateandtime >= getdate() - 60
于 2013-05-11T16:32:13.720 回答
0

尝试:

select * from mytable
where datepart(mi, dateandtime)=0 and 
      datepart(ss, dateandtime)=0 and
      datediff(d, dateandtime, getdate()) <=60
于 2013-05-11T16:34:06.720 回答
0

这帮助我获得了最高分。以“:00:00”结尾的任何内容。

WHERE (CAST(DATETIME as VARCHAR(19))) LIKE '%:00:00'
于 2021-04-30T21:51:44.737 回答