我有一张像这样的表:
DateTime A
10:00:01 2
10:00:07 4
10:00:10 2
10:00:17 1
10:00:18 3
这可以创建一个每10秒返回A平均值的查询吗?在这种情况下,结果将是:
3 (4+2)/2
2 (2+1+3)/3
提前致谢!
编辑:如果你真的认为这不能做,那就说不管! :)这是一个可以接受的答案,我真的不知道是否可以这样做。EDIT2:我正在使用SQL Server 2008.我希望有不同的分组但是已修复。例如,范围每10秒,1分钟,5分钟,30分钟,1小时和1天(只是一个例子,但类似的东西)
答案 0 :(得分:4)
在SQL Server中,您可以使用DATEPART,然后按小时,分钟和秒整数除以10分组。
CREATE TABLE #times
(
thetime time,
A int
)
INSERT #times
VALUES ('10:00:01', 2)
INSERT #times
VALUES ('10:00:07', 4)
INSERT #times
VALUES ('10:00:10', 2)
INSERT #times
VALUES ('10:00:17', 1)
INSERT #times
VALUES ('10:00:18', 3)
SELECT avg(A) -- <-- here you might deal with precision issues if you need non-integer results. eg: (avg(a * 1.0)
FROM #times
GROUP BY datepart(hour, thetime), DATEPART(minute, thetime), DATEPART(SECOND, thetime) / 10
DROP TABLE #times
答案 1 :(得分:2)
这取决于您使用的DBMS。 在Oracle中,您可以执行以下操作:
SELECT AVG(A)
FROM MYTABLE
GROUP BY to_char(DateTime, 'HH24:MI')
答案 2 :(得分:1)
有人可能会给你一个完整代码的答案,但我采用的方法是将其分解为几个较小的问题/解决方案:
(1)创建一个包含间隔的临时表。请参阅此问题的接受答案:
Get a list of dates between two dates
这个答案是针对MySQL的,但应该让你入门。谷歌搜索“创建间隔SQL”也应该产生其他方法来实现这一目标。您将需要使用主表中的MAX(日期时间)和MIN(日期时间)作为您使用的任何方法的输入(显然,跨度为10秒)。
(2)使用主表加入临时表,连接条件为(伪代码):
FROM mainTable m INNER JOIN #tempTable t ON m BETWEEN t.StartDate AND t.EndDate
(3)现在它应该像正确选择和分组一样简单:
SELECT
AVG(m.A)
FROM
mainTable m
INNER JOIN #tempTable t ON m BETWEEN t.StartDate AND t.EndDate
GROUP BY
t.StartDate
编辑如果您想查看没有记录的间隔(零平均值),则必须重新启动查询,在m.A上使用LEFT JOIN和COALESCE(参见下文)。如果你不关心看到这样的内部,那么OCary的解决方案更好/更清洁。
SELECT
AVG(COALESCE(m.A, 0))
FROM
#tempTable t
LEFT JOIN mainTable m ON m BETWEEN t.StartDate AND t.EndDate
GROUP BY
t.StartDate
答案 3 :(得分:1)
CREATE TABLE IF NOT EXISTS `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`dtime` datetime NOT NULL,
`val` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
INSERT INTO `test` (`id`, `dtime`, `val`) VALUES
(1, '2011-09-27 18:36:19', 8),
(2, '2011-09-27 18:36:21', 4),
(3, '2011-09-27 18:36:27', 5),
(4, '2011-09-27 18:36:35', 3),
(5, '2011-09-27 18:36:37', 2);
SELECT *, AVG(val) FROM test GROUP BY FLOOR(UNIX_TIMESTAMP(dtime) / 10)
答案 4 :(得分:1)
我通过使用公用表表达式来获取此数据,以获取数据的任何给定日期之间的所有时间段。原则上,您可以将间隔更改为任何SQL间隔。
DECLARE @interval_minutes INT = 5, @start_date DATETIME = '20130201', @end_date DATETIME = GETDATE()
;WITH cte_period AS
(
SELECT CAST(@start_date AS DATETIME) AS [date]
UNION ALL
SELECT DATEADD(MINUTE, @interval_minutes, cte_period.[date]) AS [date]
FROM cte_period
WHERE DATEADD(MINUTE, @interval_minutes, cte_period.[date]) < @end_date
)
, cte_intervals AS
(SELECT [first].[date] AS [Start], [second].[date] AS [End]
FROM cte_period [first]
LEFT OUTER JOIN cte_period [second] ON DATEADD(MINUTE, 5, [first].[date]) = [second].[date]
)
SELECT i.[Start], AVG(data)
FROM cte_intervals i
LEFT OUTER JOIN your_data mu ON mu.your_date_time >= i.Start and mu.your_date_time < i.[End]
GROUP BY i.[Start]
OPTION (MAXRECURSION 0)
答案 5 :(得分:0)
从http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=142634您也可以使用以下查询:
select dateadd(minute, datediff(minute, 0, timestamp ) / 10 * 10, 0), avg ( value )
from yourtable
group by dateadd(minute, datediff(minute, 0, timestamp ) / 10 * 10, 0)
有人然后扩展建议:
Select
a.MyDate,
Start_of_10_Min =
dateadd(mi,(datepart(mi,a.MyDate)/10)*10,dateadd(hh,datediff(hh,0,a.Mydate),0))
from
( -- Test Data
select MyDate = getdate()
) a
虽然我并不是他们计划如何在第二个建议中获得平均值。
就我个人而言,我更喜欢OCary's answer因为我知道那里发生了什么,并且我能够在6个月内理解它而不再重新审视它,但我完整地包含了这个。