Как мне получить медиану цен? - PullRequest
1 голос
/ 28 февраля 2020

В наборе данных каждый магазин продает несколько книг, и каждый магазин имеет свою цену для каждой книги. В данных у меня есть информация о ценах для каждой книги. С помощью запроса в Amazon Athena я хочу рассчитать среднюю цену для каждого магазина и каждого продукта за определенный период времени c.

Но, честно говоря, я понятия не имею, как это сделать. Вот мой запрос:

SELECT product_id,
       shop_id,
       XXX AS median_price
FROM data_f
    WHERE site_id = 10
            AND action <> 'base'
            AND action <> 'delete'
            AND year || month || day || hour >= '2020022500'
            AND year || month || day || hour < '2020022600'
GROUP BY product_id, shop_id

Спасибо!

Ответы [ 3 ]

1 голос
/ 28 февраля 2020

К сожалению, AWS не поддерживает функцию агрегирования median() или функции percentile(). Возможно, самый простой способ - использовать ntile(2) в подзапросе, а затем взять максимум первой плитки (или минимум второй плитки:

SELECT product_id, shop_id,
       MAX(CASE WHEN tile2 = 1 THEN price END) as median
FROM (SELECT d.*, NTILE(2) OVER (PARTITION BY product_id, shop_id ORDER BY price) as tile2
      FROM data_f d
      WHERE site_id = 10 AND
            action NOT IN ('base', 'delete') AND
            year || month || day || hour >= '2020022500' AND
            year || month || day || hour < '2020022600'
     ) d
GROUP BY product_id, shop_id;

Примечание: это, несомненно, достаточно для любого практического Однако, "медиана" обычно определяется как среднее двух средних значений, когда общее число строк четное. Если вы хотите быть pedanti c:

SELECT product_id, shop_id,
       (CASE WHEN COUNT(*) % 2 = 0
             THEN (MAX(CASE WHEN tile2 = 1 THEN price END) +
                   MIN(CASE WHEN tile2 = 2 THEN price END)
                  ) / 2.0
             ELSE MAX(CASE WHEN tile2 = 1 THEN price END)
        END) as median
1 голос
/ 28 февраля 2020

Среднее значение - это среднее значение, когда все перечислены в порядке, поэтому давайте создадим этот порядок с помощью dense_rank()

with q1 as
(
SELECT product_id,
       shop_id,
       price, 
       dense_rank() over (partition by product_id, shop_id order by price) as price_rank
FROM data_f
    WHERE site_id = 10
            AND action <> 'base'
            AND action <> 'delete'
            AND year || month || day || hour >= '2020022500'
            AND year || month || day || hour < '2020022600'
)
, q2 as 
(
select max(price_rank) as mp
from q1
)
select q1.*
from q1
where q1.price_rank = (select floor(mp/2) from q2)

Документирование оконных функций является частью документации по функциям Presto здесь

0 голосов
/ 28 февраля 2020

Ниже запрос для вычисления медианы:

with res1 as
(select id,ROW_NUMBER() over (order by id) "median_row_num" from test ),
res2 as
(select count(median_row_num) as i  from res1)
select id as "median" from res1 where res1.median_row_num = (select  case when i%2 = 0 then i/2 else i/2+1 end from res2)

Примечание: Помните, медиана - это средний элемент в отсортированном списке чисел.

, если a = [3,4,2,6,7 ]

отсортированный список a = [2,3,4,6,7]

количество элементов равно 5, поэтому медиана будет равна 4.

Но в случае, если a = [2,3,4,6,7,8]

Количество элементов 6, которое является четным числом, поэтому есть два средних элемента 4 и 6

Таким образом, медиана будет 5 ( 4 + 6 = 10/2 = 5)

Таким образом, приведенный выше запрос хорош для нечетного и четного количества, он всегда даст вам первую половину элемента.

...