postgresql — объединение таблиц с ограничением

#java #postgresql #hibernate #datetime #greatest-n-per-group

#java #postgresql #переход в спящий режим #дата и время #наибольшее число на группу

Вопрос:

Я хочу показать пользователю его сводку покупок из каждого магазина, вплоть до первых 3 покупок из каждого магазина. Для простоты количество покупок не настраивается. Итак, это не первое N, а первые 3

Допустим, у меня есть эти таблицы с этими столбцами

 Store
    id
    name

Product
    id
    name
    storeId
    price

Purchase
    id
    userId
    productId
    count
    purchaseTime
  

Это то, что я хочу отобразить

 -----------------------------------------------
| store     | product         | count | price |
-----------------------------------------------
| disney    | stitch doll     | 1     | 30  |
|           | donald cap      | 3     | 15  |
|           | ticket          | 2     | 100 |
-----------------------------------------------
| universal | iron man figure | 1     | 100 |
|           | batman figure   | 1     | 90  |
-----------------------------------------------
  

Предпочтительно, если пользователь покупает donald caps для 2 отдельных покупок (предполагается, что цена никогда не изменится), количество покупок будет объединено

например: если пользователь покупает 2 заглушки Дональда, а затем 1 заглушку, результатом будет 3 заглушки Дональда — вместо 2 заглушек Дональда и 1 заглушки Дональда

Я использую hibernate и postgresql

Я даже не знаю, с чего начать, в частности, как ограничить количество покупок в каждом магазине до 3 для каждого магазина

Любой намек, решение psudo или решения будут оценены

Спасибо

Примечание: К сожалению, с моей стороны есть серьезная оплошность. Я думаю, что хочу получить каждое резюме в 1 строке

Например

 id | Store     | Product1        | count1 | price1 | Product2      | count2 | price2 | Product3 | count3 | price3
----------------------------------------------------------------------------------------------------------------------------------
2  | Disney    | stitch doll     | 1      | 30     | donald cap    | 3      | 15     | ticket    | 2     | 100
5  | Universal | iron man figure | 1      | 100    | batman figure | 1      | 90     | null      | null  | null
  

Причина в том, что мне нужно разбить результат на страницы — отобразить 10 сводок покупок на странице
Если каждая сводка возвращает 1-3 строки, трудно определить результат на следующей странице

Комментарии:

1. » количество покупок будет объединено «, так что использование sum(count) для всех этих покупок? Или просто count(*) . Как насчет столбца цены? Должно ли это показывать цену за одну покупку или сумму всех покупок продуктов, например, рассчитывается ли цена 15 за 3 колпачка как 3 * 5 или это цена за один колпачок?

2. Сумма (количество). Цена будет индивидуальной. Спасибо

3. @Budi Как ваш вопрос связан с hibernate ?

4. Итак, вы хотите объединить покупки для каждой комбинации продукта / магазина. Вы хотите ограничить «покупку» 3 после этой агрегации? Или до агрегирования? т. Е. Если бы это было сделано раньше, 3 покупки одного и того же продукта отображались бы в виде одной строки в выходных данных.

5. Sql может быть записан как hql (язык запросов гибернации). После нахождения правильного sql я могу переименовать его в hql (по причине переносимости)

Ответ №1:

Вы могли бы использовать боковое объединение для получения первых 3 покупок в каждом магазине:

 select s.name, p.*
from store s
cross join lateral (
    select pr.name as product, pu.count, pr.price
    from purchase pu
    inner join product pr on pr.id = pu.productid
    where pr.storeid = s.id and pu.userid = ?
    order by pu.purchasetime
    limit 3
) p
  

В качестве альтернативы вы можете использовать row_number() :

 select *
from (
    select pr.name as product, pu.count, pr.price,
        row_number() over(partition by s.id order by pu.purchasetime) rn
    from purchase pu
    inner join product pr on pr.id = pu.productid
    inner join store s on s.id = pr.storeid 
    where pu.userid = ?
) t
where rn <= 3
  

Комментарии:

1. Я получил эту ОШИБКУ: столбец «pr.price» должен отображаться в предложении GROUP BY или использоваться в агрегатной функции во 2-м решении, и та же ошибка с «pr.name » в 1-м решении. Спасибо

2. @Budi: этот запрос не может вызвать эту ошибку. Вероятно, вы включили это в другой запрос, содержащий group by предложение.

3. Я получил эту ошибку после того, как я адаптировал имена, чтобы отразить мою фактическую базу данных. В любом случае, с моей стороны есть оплошность. Я обновил свое требование. Если у вас есть время, пожалуйста, дайте мне подсказку, как с этим справиться. Спасибо