Получение неверной суммы при использовании group by с внутренним соединением - PullRequest
0 голосов
/ 27 января 2020

Со ссылкой на этот вопрос ( Как получить сумму в объединенной таблице при использовании group by - получение неверных результатов ) У меня есть две таблицы orders и order_items. Мне нужно сгруппировать результаты по дням. Но мне также нужно получить сумму energy_used за каждый день из другой таблицы. Когда я пытаюсь сделать это с помощью объединения, я получаю неправильные значения order_sum за каждый день (они не суммируются). Не уверен, что я делаю неправильно.

Я хотел бы получить за каждый день

  • сумму order_items.energy_used для всех заказов, созданных в этот день
  • сумма orders.order_sum для всех заказов, созданных в этот день
  • created_at и order_sum, которые соответствуют последним order, созданным в этот день

Вот мой orders таблица

+----+-----------+---------+---------------------+
| id | order_sum | user_id | created_at          |
+----+-----------+---------+---------------------+
| 1  | 25.13     | 7       | 2020-01-25 09:13:00 |
| 2  | 10.00     | 7       | 2020-01-25 15:23:00 |
| 3  | 14.00     | 5       | 2020-01-26 10:14:00 |
| 4  | 35.00     | 1       | 2020-01-27 11:13:00 |
+----+-----------+---------+---------------------+

А вот и моя order_items таблица

+----+----------+-------------+---------------------+
| id | order_id | energy_used | created_at          |
+----+----------+-------------+---------------------+
| 1  | 1        | 65          | 2020-01-25 09:13:00 |
| 2  | 1        | 12          | 2020-01-25 09:13:00 |
| 3  | 2        | 70          | 2020-01-26 10:14:00 |
| 4  | 2        | 5           | 2020-01-26 10:14:00 |
| 5  | 3        | 0           | 2020-01-27 11:13:00 |
+----+----------+-------------+---------------------+

И это желаемый результат, которого я пытаюсь достичь

+---------------+-----------------+-------------------+---------------------+----------------+
| date_of_month | total_order_sum | total_energy_used | last_order_date     | last_order_sum |
+---------------+-----------------+-------------------+---------------------+----------------+
| 2020-01-25    | 35.13           | 77                | 2020-01-25 09:13:00 | 25.13          |
| 2020-01-26    | 14.00           | 75                | 2020-01-26 10:14:00 | 14.00          |
| 2020-01-27    | 35.00           | 0                 | 2020-01-27 11:13:00 | 35.00          |
+---------------+-----------------+-------------------+---------------------+----------------+

И вот запрос, который я пробовал, но я получаю неправильные результаты, порядок_сум не рассчитывается правильно. Он показывает то же, что и last_order_sum

select 
    date(o.created_at) date_of_month,
    i.total_energy_used,
    o.created_at last_order_date,
    o.order_sum last_order_sum,
    sum(order_sum) as total_order_sum
from orders o
inner join (
    select date(o1.created_at) date_of_month, sum(i1.energy_used) total_energy_used
    from orders o1
    inner join order_items i1 on o1.id = i1.order_id
    group by date(o1.created_at)
) i on i.date_of_month = date(o.created_at)
where o.created_at = (
    select max(o1.created_at)
    from orders o1
    where date(o1.created_at) = date(o.created_at)
)

Вот скрипка: https://dbfiddle.uk/?rdbms=mysql_5.6&fiddle=92b8cc2920ad9f7a7cdd56bded5a3bf2

Ответы [ 3 ]

2 голосов
/ 27 января 2020

Всегда объединяйте таблицы вместе по их отношениям (в данном случае orders.id с order_items.order_id), а затем группируйте. чтобы избежать дублирования order_sums для нескольких order_items при объединении, сначала группируйте order_items по order_id.

select 
    date(o.created_at) date_of_month,
    sum(i.total_energy_used),
    max(o.created_at),
    sum(order_sum) as total_order_sum
from orders o
inner join (
    select order_id, sum(total_energy_used) total_energy_used
    from order_items i
    group by order_id
) i on o.id = i.order_id
group by date(o.created_at)

с этого момента вы можете снова выполнить объединение для заказов с max (o.created_at), чтобы получить order_sum для последний заказ. Мораль этой истории: следите за гранулярностью.

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

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

select so.dtDay as date_of_month, so.order_sum as total_order_sum,
   eu.energy_used as total_energy_used,
   o.created_at as last_order_date,
   o.order_sum as last_order_sum
from (
select left(created_at,10) as dtDay, sum(order_sum) as order_sum, max(id) as last_insert_id
from orders
group by left(created_at,10)
order by created_at
) so
inner join orders o on o.id = so.last_insert_id
left join (select left(created_at,10) as dtDay, sum(energy_used) as energy_used
from order_items
group by left(created_at,10)) eu on so.dtDay = eu.dtDay;

DBFiddle

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

Ваша проблема в том, что вы выбираете из orders, где вы на самом деле хотите получить совокупность orders по дате. Так что выберите из двух агрегирующих подзапросов, к которым вы присоединяетесь. Единственная проблема - last_order_sum, которую мы можем выбрать в следующем подзапросе, как только мы узнаем дату последнего заказа.

select 
  order_date,
  o.total_order_sum,
  oi.total_energy_used,
  o.last_order_date,
  (
    select order_sum
    from orders last_order
    where lastorder.created_at = o.last_order_date
  ) as last_order_sum
from 
(
  select
    date(created_at) as order_date,
    sum(order_sum) as total_order_sum,
    max(created_date) as last_order_date
  from orders
  group by date(created_at)
) o
inner join 
(
  select
    date(created_at) as order_date,
    sum(energy_used) as total_energy_used
  from order_items
  group by date(created_at)
) oi using(order_date)
order by order_date;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...