добавление столбца в запрос без вставки его в предложение GROUP BY

#sql #postgresql #greatest-n-per-group

#sql #postgresql #наибольшее число на группу

Вопрос:

Я пытаюсь выбрать следующие данные из моей базы данных о продаже продукта: недавняя покупка каждого продукта, цена продажи и product_id. все в одном запросе.

сначала я создал запрос для сбора только идентификатора продукта_id и последних продаж каждого продукта (без цены), сгруппированных по идентификатору продукта_id, и он работал нормально. вот запрос:

 SELECT product_id,
        max(sold_date)
FROM sold_list
GROUP BY product_id
ORDER BY product_id
  

НО когда я пытаюсь добавить столбец sold_price, postgres заставляет меня поместить sold_price в предложение GROUP BY . и когда я это делаю, я начинаю получать более одной покупки определенного продукта вместо того, чтобы иметь только недавнюю покупку каждого продукта.

это то, что я пробовал:

 SELECT product_id,
       max(sold_date),
       sold_price
FROM sold_list
GROUP BY product_id, sold_price
ORDER BY product_id
  

Каков способ объединить эти 3 столбца вместе и иметь только одну недавнюю покупку каждого product_id (каждый product_id должен отображаться только один раз в столбце)?

Ответ №1:

С PostgreSQL вы можете использовать distinct on :

 SELECT distinct on (product_id) product_id, sold_date, sold_price
  FROM sold_list
 ORDER BY product_id, sold_date desc
  

Ответ №2:

Вам нужно объединить столбец, если его нет в group by .

Одним из возможных способов может быть использование array_agg (Postgres Aggregate Functions Docs)

 SELECT product_id,
       max(sold_date),
       array_agg(sold_price), -- all the sold_price
       array_agg(DISTINCT sold_price) -- unique sold_price
FROM sold_list
GROUP BY product_id
ORDER BY product_id
  

Это вернет столбец с массивом.

Ответ №3:

Ваше описание наводит меня на мысль, что вам нужны каждая sold_price и последняя (максимальная) дата продажи продукта. Если это так, то вы можете создать CTE, чтобы получить дату, а затем перейти к основному выбору, собирая продукт и цены. См. fiddle .

 with prod_date(product_id, sold_date) as
     (select product_id, max(sold_date) 
        from sold_list
       group by product_id
     )
select sl.product_id
     , pd.sold_date max_sold_date 
     , sl.sold_price
  from sold_list sl
  join prod_date pd on pd.product_id=sl.product_id  
 order by product_id;