如何在SQL中计算由风速加权的平均风向

时间:2018-06-29 03:55:31

标签: sql-server database rdbms

我有一个SQL Server数据库,该数据库具有一个包含一秒数据的数据表。该表包括以下列:

DataId
DataType
NumericValue
PostDate

WindSpeed is one data type
Wind Direction is a second

最终,我希望有一个存储过程,可以发送开始和结束datetime以及平均时间间隔(以分钟为单位)。到目前为止,我所拥有的是以下内容,但它不起作用。

select 
    'avgWD' = case
                 when weather.OuvWithoutFlow > 180 
                    then sum(weather.OuvWithoutFlow - 180)
                 when weather.OuvWithoutFlow < 180 
                    then sum(weather.OuvWithoutFlow + 180)
                 else sum(weather.OuvWithoutFlow + 0)
              end
from
    (select 
         (atan(((-1/(cast(count(*) as float)))*(sum(WD_sin)))/((-1/(cast(count(*) as float)))*(sum(WD_cos))))) as OuvWithoutFlow
     from
         (select 
              d_WS.numericvalue as WS,
              sin(d_WD.WD) as WD_sin,
              cos(d_WD.WD) as WD_cos,
              d_WD.WD, d_WS.PostDate
          from 
              (select Top 10 * 
               from datum 
               where datum.DatTypeID = @ParameterID_WS) as d_WS
       cross apply 
           (select numericvalue as WD 
            from datum 
            where datum.DatTypeID = @ParameterID_WD 
              and datum.postdate = d_WS.postdate) as d_WD) wind
    ) weather 
group by 
    weather.OuvWithoutFlow

使用此数据集将返回180.784167303869,这是错误的。

WS           WD_Sin             WD_COS              WD          PostDate
0.720000    0.632170969166108   0.344615533230271   214.700000  2018-05-21 21:50:03.0000000
0.977000    -0.520565399773975  0.82676518102673    200.500000  2018-05-21 21:50:04.0000000
1.132000    1.01064916139673    -0.509913985460376  203.100000  2018-05-21 21:50:05.0000000
1.183000    -0.859512457376702  -0.812851361328911  211.300000  2018-05-21 21:50:06.0000000
0.977000    -0.478215500921105  0.851961815270366   219.400000  2018-05-21 21:50:07.0000000
1.183000    0.555198984923194   1.04462581202087    220.400000  2018-05-21 21:50:08.0000000
0.926000    0.922867100571996   0.0761072577474554  221.400000  2018-05-21 21:50:09.0000000
1.029000    -0.686290821523267  -0.76671109832382   217.500000  2018-05-21 21:50:10.0000000
0.977000    0.102716204322373   0.971585498743988   226.300000  2018-05-21 21:50:11.0000000
1.080000    0.489014249853966   -0.962946033503313  216.300000  2018-05-21 21:50:12.0000000

1 个答案:

答案 0 :(得分:2)

Upworks帮了忙。

    SET NOCOUNT ON;

;WITH 
     WindDirection 
     AS (SELECT d.PostDate, 
                d.NumericValue AS Direction 
         FROM   Datum AS d
         WHERE  ( d.ParameterId = @ParameterID_WD )), 
     WindSpeed 
     AS (SELECT d.PostDate, 
                d.NumericValue AS Speed 
         FROM   Datum  AS d
         WHERE  ( d.ParameterId = @ParameterID_WS )), 
     DatumCombined 
     AS (SELECT wd.postdate, 
                wd.direction, 
                ws.speed 
         FROM   WindDirection AS wd 
                INNER JOIN WindSpeed AS ws 
                        ON wd.PostDate = ws.PostDate), 
     DirectionRadians 
     AS (SELECT dc.Direction * Pi() / 180. AS [radians], 
                dc.PostDate, 
                dc.Speed 
         FROM   DatumCombined AS dc), 
     postdate 
     AS (SELECT Dateadd(minute, Datediff(minute, 0, dr.PostDate) / @interval * @interval, 0 ) AS postdate, 
                x = Avg(Sin(radians) * dr.Speed), 
                y = Avg(Cos(radians) * dr.Speed) 
         FROM   DirectionRadians AS dr
         GROUP  BY Dateadd(minute, Datediff(minute, 0, dr.PostDate) / @interval * @interval, 0)), 
     AverageRadiansByIntervals 
     AS (SELECT di.PostDate, 
                CASE 
                  WHEN di.x >= 0 
                       AND di.y >= 0 THEN 0 + Atan(di.x/di.y) 
                  WHEN di.x >= 0 
                       AND di.y < 0 THEN Pi() - Atan(di.x /-di.y) 
                  WHEN di.x < 0 
                       AND di.y < 0 THEN Pi() + Atan(-di.x/-di.y) 
                  WHEN di.x < 0 
                       AND di.y >= 0 THEN 2 * Pi() - Atan(-di.x /di.y) 
                END AS AverageRadians 
         FROM   PostDate AS di) 

SELECT ar.postdate, 
       ar.AverageRadians * 180. / Pi() numericvalue 
FROM  AverageRadiansByIntervals AS ar
WHERE ar.PostDate >= @StartDate AND ar.PostDate < @EndDate
ORDER  BY ar.PostDate