SQL: Как сгруппировать по двум таблицам? - PullRequest
0 голосов
/ 06 ноября 2018

У меня есть таблицы Продукты и История , и мне нужно сгруппировать по имени:

products = ( id_product , name)

history = ( id_history , id_product, количество)

Я пробовал этот SQL-запрос, но он не сгруппирован по имени:

SELECT
      products.name,
      sum(history.amount)
FROM history
INNER JOIN products ON history.id_product = products.id_product
GROUP BY
      products.name,
      history.amount,
      history.id_history;

Это результат:

SQL result

Ответы [ 2 ]

0 голосов
/ 06 ноября 2018

Это не ответ, но слишком долго для комментария.

Для удобства чтения таблица продуктов должна быть первой. В конце концов, это продукты, которые мы выбираем, плюс сумма истории, к которой мы можем получить доступ через [left] join history ..., за которым следует агрегация, или [left] join (<history aggregation query>), или подвыбор в предложении select.

Еще одним шагом для улучшения читаемости является использование псевдонимов.

Присоединиться к таблице, затем агрегировать

select p.name, coalesce(sum(h.amount), 0) as total
from products p
left join history h on h.id_product = p.id_product
group by p.name
order by p.name;

Объединить, затем присоединиться

select p.name, coalesce(h.sum_amount, 0) as total
from products p
left join
(
  select sum(h.amount) as sum_amount
  from history 
  group by id_product
) h on h.id_product = p.id_product
order by p.name;

Получить сумму в предложении select

select
  name,
  (select sum(amount) from history h where h.id_product = p.id_product) as total
from products p
order by p.name;

И поскольку вы не понимали, как использовать GROUP BY, вот объяснение: GROUP BY ___ означает, что вы хотите одну строку результатов на ___. В исходном запросе у вас было GROUP BY products.name, history.amount, history.id_history, в котором говорилось, что вам нужна одна строка результата на имя, сумму и идентификатор, в то время как на самом деле вам нужна только одна строка на имя, т.е. GROUP BY products.name.

0 голосов
/ 06 ноября 2018

Вы должны группировать только по тем атрибутам, которые необходимо агрегировать. В этом случае вам нужно только products.name.

SELECT
      products.name,
      sum(history.amount) AS [Amount]
FROM history
INNER JOIN products ON history.id_product = products.id_product
GROUP BY
      products.name;

Если вам нужно включить продукты без истории (при условии, что сумма должна быть 0 вместо null в этом случае), тогда вы можете использовать OUTER JOIN вместо INNER JOIN, чтобы включить все продукты:

SELECT
      products.name,
      COALESCE(sum(history.amount), 0) AS [Amount]
FROM history
    RIGHT OUTER JOIN products ON history.id_product = products.id_product
GROUP BY
      products.name;
...