簡體   English   中英

SQL Server - 選擇所有頂部的小時記錄

[英]SQL Server - Select all top of the hour records

我有一個大表,每秒鍾創建一次記錄,並且只想選擇過去 2 個月內每小時創建的記錄。 因此,我們將在過去 60 天內每天獲得 24 條選定記錄

表結構為Dateandtime、Value1、Value2等

非常感謝

您可以在日期部分( cast(col1 as date) )和小時部分( datepart(hh, col1)group by 。然后選擇每小時的最小日期,並對其進行過濾:

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
        ...

為清楚起見,我可能會使用基於 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

另外:我不確定您所說的“小時前”究竟是什么意思 - 在每小時開始時創建的行(例如在04:00:00 ) - 或者更確切地說是在那個小時創建的最后一行時間跨度? 如果您的意思是每小時的第一個 - 那么您需要將ORDER BY DateAndTime DESC更改為ORDER BY DateAndTime ASC

您可以將選項與 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)

您可以為此使用窗口函數:

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子句定義的每個組分配一個序列號——在這種情況下,每天的每個小時。 在該組中,它按日期和dateandtimedateandtime ,因此最接近小時頂部的值為 1。外部查詢只是為每個組選擇這一條記錄。

您可能需要一個額外的過濾器子句來獲取過去 60 天內的記錄。 在子查詢中使用它:

where dateandtime >= getdate() - 60

嘗試:

select * from mytable
where datepart(mi, dateandtime)=0 and 
      datepart(ss, dateandtime)=0 and
      datediff(d, dateandtime, getdate()) <=60

這幫助我獲得了最高分。 以“:00:00”結尾的任何內容。

WHERE (CAST(DATETIME as VARCHAR(19))) LIKE '%:00:00'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM