使用sql average和日期和时间

时间:2015-06-14 23:02:47

标签: sql sql-server tsql

我有一个大赛马数据库,我想查询。

我想要做的是创建一个新列(平均草皮速度),以便在当天比赛之前和特定比赛类型(草坪)中找到马的平均速度(仅过去1年)。

我以前在excel中使用averageifs formular来做这个,但是有了这么多的数据,程序会一直冻结并挂起,所以我打算转移到sql。

我已经采用了一个非常小的样本并将其简化为演示目的,我知道它将包含许多空值,但希望您理解我的问题。

因此,例如,如果我们在2015年5月21日的最后一场比赛中看到Aazif他在那天比赛之前的平均速度我们会忽略第一场比赛,因为它超出了日期范围和错误的比赛类型但我们会从第二场和第三场比赛拿下70和40分,平均给我们55分

Date and time       Horse    Race Type  Speed Rating  Average Turf Speed
10/05/2013 14:00    Aazif    AW         60  
10/05/2013 14:00    Bix      AW         50  
10/05/2013 14:00    Camelot  AW         40  
15/08/2014 15.00    Aazif    Turf       70  
15/08/2014 15.00    Bix      Turf       60  
15/08/2014 15.00    Camelot  Turf       50  
17/05/2015 13.00    Aazif    Turf       40  
17/05/2015 13.00    Bix      Turf       30  
17/05/2015 13.00    Camelot  Turf       20  
21/05/2015 14.00    Aazif    Turf       50         
21/05/2015 14.00    Bix      Turf       40  
21/05/2015 14.00    Camelot  Turf       30  

5 个答案:

答案 0 :(得分:1)

我不确定您对大型数据库的定义"对数据库引擎来说很大。通常我会通过更高效的左连接来做到这一点,但是在那天的比赛之前你会给出一个很难的标准"这使得以这种方式编写变得困难。所以我在下面有一个可以提供你想要的东西,但可能会出现性能问题,因为组成最后一列的子查询([Prev Speed Rating])会触发每一行。如果速度很慢,首先尝试使用where子句中使用的列进行复合索引。

    create view vHorseResults
    as
    select a.Horse, 
    a.[Race Type], 
    a.[Speed Rating],
    a.[date and time], 
        (select avg(b.[Speed Rating]) 
         from Races b 
         where a.Horse = b.Horse 
          and a.[Race Type] = b.[Race Type]
          and a.[date and time] > b.[date and time]
          and b.[date and time] >= dateadd(year, -1, getdate()) 
             as [Prev Speed Rating] 
    from Races a


    -- show 1 years worth of data.
        select * 
        from vHorseResults
        where getdate() >= datediff(year,-1,[date and time])

答案 1 :(得分:0)

select avg([turf speed]) 
where 
    [date and time] between [date and time] 
    and datediff(d,-365,[date and time])
    and type='turf'

答案 2 :(得分:0)

select Horse, [Race Type], avg([turf speed]) 
from table 
where [date and time] >= DateAdd(yy, -1, GetDate())
group by Horse, [Race Type]

答案 3 :(得分:0)

使用此

--create temp table for data sample
DECLARE @yourdata AS TABLE
    (
      [Date and time] DATETIME ,
      Horse NVARCHAR(30) ,
      [Race Type] NVARCHAR(30) ,
      [Speed Rating] FLOAT
    )
INSERT  INTO @yourdata
        ( [Date and time], Horse, [Race Type], [Speed Rating] )
VALUES  ( '2013-05-10 14:00:00', 'Aazif', 'AW', 60 ),
        ( '2013-05-10 14:00:00', 'Bix', 'AW', 50 ),
        ( '2013-05-10 14:00:00', 'Camelot', 'AW', 40 ),
        ( '2014-05-15 15:00:00', 'Aazif', 'Turf', 70 ),
        ( '2014-05-15 15:00:00', 'Bix', 'Turf', 60 ),
        ( '2014-05-15 15:00:00', 'Camelot', 'Turf', 50 ),
        ( '2015-05-17 13:00:00', 'Aazif', 'Turf', 40 ),
        ( '2015-05-17 13:00:00', 'Bix', 'Turf', 30 ),
        ( '2015-05-17 13:00:00', 'Camelot', 'Turf', 20 ),
        ( '2015-05-21 14:00:00', 'Aazif', 'Turf', 50 ),
        ( '2015-05-21 14:00:00', 'Bix', 'Turf', 40 ),
        ( '2015-05-21 14:00:00', 'Camelot', 'Turf', 30 )  

--Final query
--1. Ignore the last race
--2. Ignore the race with wrong race type

SELECT  T.Horse ,
        AVG(T.[Speed Rating]) AS [Average Turf Speed]
FROM    ( SELECT    * ,
                    ROW_NUMBER() OVER ( PARTITION BY Y.Horse, Y.[Race Type] ORDER BY Y.[Date and time] DESC ) AS RN
          FROM      @yourdata AS Y
        ) AS T
WHERE   T.[Race Type] = 'Turf'
        AND T.RN <> 1
GROUP BY T.Horse

输出

enter image description here

如果需要在最后一次未被忽视的比赛中获得一年的平均值,请使用:

--Final query
--1. Ignore the last race
--2. Ignore the race with wrong race type
--3. get average in one year range from the last not ignored race

SELECT  Y.Horse ,
        AVG(Y.[Speed Rating]) AS [Average Turf Speed]
FROM    ( SELECT    * ,
                    ROW_NUMBER() OVER ( PARTITION BY Y.Horse, Y.[Race Type] ORDER BY Y.[Date and time] DESC ) AS RN ,
                    MAX(Y.[Date and time]) OVER ( PARTITION BY Y.Horse,
                                                  Y.[Race Type] ) AS newlast
          FROM      @yourdata AS Y
        ) Y
WHERE   CONVERT(DATE, Y.[Date and time]) BETWEEN CONVERT(DATE, DATEADD(YEAR,
                                                              -1, Y.newlast))
                                         AND     CONVERT(DATE, Y.newlast)
        AND Y.RN <> 1
        AND Y.[Race Type] = 'Turf'
GROUP BY Y.Horse

输出

enter image description here

答案 4 :(得分:0)

DECLARE @Table table
(
    [DateTime] datetime,
    Horse varchar(20),
    RaceType varchar(40),
    Speed int
)


INSERT @Table VALUES
(CONVERT(datetime, '10/05/2013 14:00',103),'Aazif','AW','60'),
(CONVERT(datetime, '10/05/2013 14:01',103),'Bix','AW','50'),
(CONVERT(datetime, '10/05/2013 14:02',103),'Camelot','AW','40'),
(CONVERT(datetime, '15/08/2014 15:00',103),'Aazif','Turf','70'),
(CONVERT(datetime, '15/08/2014 15:00',103),'Bix','Turf','60'),
(CONVERT(datetime, '15/08/2014 15:00',103),'Camelot','Turf','50'),
(CONVERT(datetime, '17/05/2015 13:00',103),'Aazif','Turf','40'),
(CONVERT(datetime, '17/05/2015 13:00',103),'Bix','Turf','30'),
(CONVERT(datetime, '17/05/2015 13:00',103),'Camelot','Turf','20'),
(CONVERT(datetime, '21/05/2015 14:00',103),'Aazif','Turf','50'),
(CONVERT(datetime, '21/05/2015 14:00',103),'Bix','Turf','40'),
(CONVERT(datetime, '21/05/2015 14:00',103),'Camelot','Turf','30')

SELECT 
    *
FROM    
    @Table data
    OUTER APPLY
    (
        SELECT AVG(Speed) AS AverageSpeedOfPreviousYear 
        FROM @Table 
        WHERE 
            [DateTime] < data.[DateTime] 
            AND DATEDIFF(YEAR, [DateTime], data.DateTime) <= 1 
            AND Horse = data.Horse 
            AND RaceType = data.RaceType
    ) avg

<强>结果

DateTime                Horse                RaceType Speed       AverageSpeedOfPreviousYear
----------------------- -------------------- -------- ----------- --------------------------
2013-05-10 14:00:00.000 Aazif                AW       60          NULL
2013-05-10 14:01:00.000 Bix                  AW       50          NULL
2013-05-10 14:02:00.000 Camelot              AW       40          NULL
2014-08-15 15:00:00.000 Aazif                Turf     70          NULL
2014-08-15 15:00:00.000 Bix                  Turf     60          NULL
2014-08-15 15:00:00.000 Camelot              Turf     50          NULL
2015-05-17 13:00:00.000 Aazif                Turf     40          70
2015-05-17 13:00:00.000 Bix                  Turf     30          60
2015-05-17 13:00:00.000 Camelot              Turf     20          50
2015-05-21 14:00:00.000 Aazif                Turf     50          55
2015-05-21 14:00:00.000 Bix                  Turf     40          45
2015-05-21 14:00:00.000 Camelot              Turf     30          35