Средняя цена за кластер - PullRequest
       9

Средняя цена за кластер

0 голосов
/ 15 января 2020

Я тестирую этот код.

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

В этом случае у меня просто один идентификатор и один кластер, но в большинстве случаев у меня будет несколько идентификаторов в одном кластере. Наконец, я возвращаюсь на 171 день, потому что у меня может быть до 171 дня данных на один идентификатор, но это может быть намного меньше, например, менее 10 дней данных на один идентификатор. Интересно, может ли это сделать кодировка 171 или что-то вроде максимального числа дней для каждого идентификатора.

Ответы [ 4 ]

1 голос
/ 15 января 2020

На самом деле, ваше среднее значение вычисляется по последним 171 скользящим последним строкам, поэтому оно меняется для каждой строки.

Я думаю, что вам нужен фильтр для даты в * Предложение 1005 * и OVER() без ORDER BY:

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())
0 голосов
/ 15 января 2020

Похоже, то, что вы ищете, представляет собой простое среднее значение, сгруппированное на уровне 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
0 голосов
/ 15 января 2020

Добавить раздел по идентификатору к существующему многораздельному кластеру как

Partition by ID, CLUSTER..

Как вы сказали, данные также имеют кластеризацию по идентификатору, вы можете добавить этот идентификатор, как указано выше, чтобы получить то же самое. Среднее значение, возвращаемое теперь, будет средним числом строк кластеризации

0 голосов
/ 15 января 2020

То, что вы видите, является скользящим средним от цены.

Функция управления окнами просматривает все строки, «предшествующие» текущей строке. Следовательно, первая строка в выходных данных совпадает с ценой, вторая - средним из первых 2 и c.

Я думаю, что вам нужно создать CTE, который усреднит цену по каждому кластер (и идентификатор, если необходимо), а затем JOIN, что обратно на идентификатор и кластер

...