【问题标题】:Average price per Cluster每个集群的平均价格
【发布时间】:2020-01-14 23:04:46
【问题描述】:

我正在测试这段代码。

SELECT ID, Cluster, Date, Price,
    AVG(Price) OVER (PARTITION BY Cluster ORDER BY Date ROWS BETWEEN 171 PRECEDING AND CURRENT ROW) As ClusterAverage
FROM tblCluster
WHERE LEN(ID) = 9 AND IDNOT LIKE '%[^a-Z0-9]%'
   AND Cluster in ('430.00')

我想我会得到一个 ClusterAverage 的平均价格。我认为这就是'PARTITION BY Cluster' 所做的。相反,我明白了。

ID          Cluster Date        Price       ClusterAverage
50064FAL8   430     6/14/2019   115.5827    115.5827
50064FAL8   430     6/17/2019   115.694     115.63835
50064FAL8   430     6/19/2019   116.5761    115.9509333
50064FAL8   430     6/21/2019   116.1692    116.0055
50064FAL8   430     6/25/2019   117.2248    116.24936
50064FAL8   430     6/27/2019   117.0839    116.38845
50064FAL8   430     6/28/2019   117.0156    116.4780429
50064FAL8   430     6/30/2019   118.2286    116.6968625

在这种情况下,我只有一个 ID 和一个集群,但在大多数情况下,我会在一个集群中拥有多个 ID 号。最后,我要返回 171 天,因为每个 ID 最多可以有 171 天的数据,但它可以少得多,比如每个 ID 不到 10 天的数据。我想知道是否将其编码为 171 是这样做的方法,还是每个 ID 的某种 count-max-days。

【问题讨论】:

  • 你想要的实际结果集是什么?听起来您几乎只需要一个简单的非窗口 AVG() 聚合。

标签: sql sql-server tsql window-functions


【解决方案1】:

实际上,您的平均值是在滚动的最后 171 行中计算得出的,因此它会随每一行而变化。

我认为您希望在 WHERE 子句中的日期上使用 过滤器,而在没有 ORDER BY 的情况下使用 OVER()

SELECT 
    ID, 
    Cluster, 
    Date, 
    Price,
    AVG(Price) OVER (PARTITION BY Cluster) As ClusterAverage
FROM tblCluster
WHERE 
    LEN(ID) = 9 
    AND ID NOT LIKE '%[^a-Z0-9]%'
    AND Cluster in ('430.00')
    AND Date > DATEADD(day, 171, getdate())

如果您需要对计算平均值的日期范围进行更细粒度的控制,您还可以使用条件聚合:

SELECT 
    ID, 
    Cluster, 
    Date, 
    Price,
    AVG(CASE WHEN Date > DATEADD(day, 10, getdate()) THEN Price END) 
        OVER (PARTITION BY Cluster) As ClusterAverageLast10Days,
    AVG(CASE WHEN Date > DATEADD(day, 20, getdate()) THEN Price END) 
        OVER (PARTITION BY Cluster) As ClusterAverageLast20Days,
    AVG(Price) OVER (PARTITION BY Cluster) As ClusterAverageOverall
FROM tblCluster
WHERE 
    LEN(ID) = 9 
    AND ID NOT LIKE '%[^a-Z0-9]%'
    AND Cluster in ('430.00')
    AND Date > DATEADD(day, 171, getdate())

【讨论】:

  • 也许我没有像我应该的那样描述这个问题,但我认为你把它钉在了 GMB 上!现在对我来说已经晚了。我明天要仔细看看。谢谢。
【解决方案2】:

您看到的是价格的滚动平均值。

窗口函数正在查看当前行“之前”的所有行。因此输出中的第一行与价格相同,第二行是前 2 行的平均值,以此类推。

我认为您需要创建一个 CTE,对每个集群的价格(如果需要,还包括 ID)进行平均,然后将 JOIN 返回到 ID 和集群上

【讨论】:

    【解决方案3】:

    按 ID 将分区添加到现有的分区集群为

    Partition by ID, CLUSTER..
    

    正如您所说,数据也具有 id 明智的聚类,您可以像上面一样添加此 id 以产生相同的结果。现在返回的平均值将是 idwise 聚类行平均值

    【讨论】:

      【解决方案4】:

      看起来您正在寻找的是在 ID 和集群级别分组的简单平均值。如果是这样:

      SELECT ID, Cluster,
          AVG(Price) as ClusterAverage
      FROM tblCluster
      WHERE LEN(ID) = 9 AND IDNOT LIKE '%[^a-Z0-9]%' AND Date>DATEADD(day,-171,GETDATE())
      GROUP BY ID, Cluster
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-11
        • 1970-01-01
        • 2021-05-08
        • 2019-02-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多