SQL Server-选择所有最热门的小时记录
我有一个很大的表,每秒钟创建一次记录,只想选择在过去2个月内每小时顶部创建的记录。因此,在过去60天中,我们每天都会得到24条选定的记录 表结构为Dateandtime、Value1、Value2等 非常感谢您可以按日期部分castcol1作为日期和小时部分dateparthh,col1分组。然后选择每小时的最短日期,并根据该日期进行筛选:SQL Server-选择所有最热门的小时记录,sql,sql-server,Sql,Sql Server,我有一个很大的表,每秒钟创建一次记录,只想选择在过去2个月内每小时顶部创建的记录。因此,在过去60天中,我们每天都会得到24条选定的记录 表结构为Dateandtime、Value1、Value2等 非常感谢您可以按日期部分castcol1作为日期和小时部分dateparthh,col1分组。然后选择每小时的最短日期,并根据该日期进行筛选: select * from YourTable yt join ( select min(dateandtime) as d
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
您可以为此使用窗口功能:
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
尝试:
为了清楚起见,我可能会使用一种基于CTE的两步方法,这种方法适用于SQL Server 2005和更新版本-您没有明确指定正在使用哪个版本的SQL Server,所以我希望您不再使用像2000这样的古老版本:
另外:我不确定你所说的“小时顶部”到底是什么意思——即在每小时开始时创建的行,例如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
)
这帮我度过了最紧张的时刻。任何以:00:00结尾的内容
WHERE (CAST(DATETIME as VARCHAR(19))) LIKE '%:00:00'
清楚地向我们展示您在每个小时的最佳时段尝试了什么,例如“2013-05-11 09:00:00.000”,而不是“2013-05-11 09:00:01.000”等等。您想要的精度级别将有助于确定哪些时间元素是有效的标准。这似乎很危险,因为它假设所有记录都是,在给定的一秒钟内记录下每一秒,并且没有重复。@GordonLinoff:的确-这是我对问题的解释,问题的每一秒都有记录。对后者做得很好。这是一个很好的修剪解决方案。
-- 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
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
)
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)
WHERE (CAST(DATETIME as VARCHAR(19))) LIKE '%:00:00'