Использование grouby и sum в запросе

У меня довольно большой запрос, и я пытаюсь получить сумму столбца orders.price. С приведенным ниже кодом он возвращает всего 44,00, что является ценой для первой строки. Когда я запускаю необработанный SQL, он возвращает столбец с более чем 1000 строками цен в столбце под названием «AGGREGATE». Я хочу вернуть единую сумму по всем этим ценам.

Когда я удаляю groupBy, он работает в основном нормально. Тем не менее, groupby есть, поскольку я, кажется, получаю повторяющиеся строки обратно.

$query = Order::leftJoin('customers', 'orders.customer_id', '=', 'customers.customer_id')
    ->leftJoin('addresses', 'orders.order_id', '=', 'addresses.order_id')
    ->where('orders.customer_id', '!=', 0);

$query->whereIn('user_id', [3, 5, 10, 15]);

$query->groupBy('orders.order_id');

$sum = $query->sum('orders.price');

Я пропустил здесь часть кода, но соединения действительно необходимы.

Вот сгенерированный SQL:

SELECT
    sum(`orders`.`price`) AS AGGREGATE
FROM
    `orders`
LEFT JOIN `customers` ON `orders`.`customer_id` = `customers`.`customer_id`
LEFT JOIN `addresses` ON `orders`.`order_id` = `addresses`.`order_id`
WHERE
    `orders`.`customer_id` IS NOT NULL
AND `orders`.`customer_id` != '0'
AND `orders`.`user_id` IN (3, 5, 10, 15)
GROUP BY
    `orders`.`order_id`
ORDER BY
    `orders`.`order_id` DESC

У вас может быть ошибка в вашей первой строке прямо здесь: Order::leftJoin('customers', 'customers.customer_id', '=', 'customers.customer_id') - вы присоединяетесь к customers.customer_id с customers.customer_id.

Namoshek 01.05.2018 14:37

Да, спасибо, что указали на это. Та ошибка как раз откуда я немного переписал для SO. Отредактировано

roweneil 01.05.2018 14:40

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

Namoshek 01.05.2018 14:42

Я добавил сгенерированный SQL к своему вопросу. Приветствую за помощь

roweneil 01.05.2018 15:01

Что ж, вам явно следует избавиться от groupBy, если вы хотите иметь только один общий результат вместо одного результата на группу (который, кстати, вы могли сопоставить только с orders.order_id в select). Мне также кажется, что оба ваших left joins полностью устарели, потому что вы не используете эти таблицы ни в пунктах where, ни в select. Однако левые соединения не ограничивают результат в вашем случае. - Может быть, было бы неплохо спросить, каков ваш желаемый результат. Я предполагаю общую стоимость всех заказов всех клиентов для некоторых конкретных пользователей?

Namoshek 01.05.2018 15:17

@Namoshek Как я уже сказал в своем первоначальном вопросе, я пропустил некоторые запросы, поскольку они не имеют отношения к вопросу. У меня есть другие предложения where, которые требуют этих объединений.

roweneil 01.05.2018 15:20

Как и в моем первоначальном вопросе, я хотел бы вернуть одно число, которое является суммой всех orders.price.

roweneil 01.05.2018 15:35

Я имею в виду, что запрос, который вы показали до сих пор, в основном выполняет это (см. скрипку), что мне кажется абсолютно нормальным. Но я предполагаю, что вам нужно что-то вроде это, что по сути является тем же запросом без group by и order by. Более подробным примером может быть это.

Namoshek 01.05.2018 15:40

К сожалению, мне нужны эти объединения, а также groupby, чтобы остановить дублирование. Запрос строится на основе дюжины или около того условий (по сути, это система расширенного поиска). Так, например, это может быть добавлено: $query->whereIn('addresses.postcode', ['ab123ab']); Может быть, лучше спросить, как можно выполнить это соединение (один заказ может иметь ноль, один или несколько адресов), не получая дубликатов и не требуя groupBy?

roweneil 01.05.2018 15:44

Вы можете выполнить это как часть соединения и использовать inner join вместо left join. Примерно так должно работать: ... FROM orders INNER JOIN addresses ON addresses.order_id = orders.order_id AND addresses.postcode IN ('ab123', 'bc234').

Namoshek 01.05.2018 16:00
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Поиск нового уровня в Laravel с помощью MeiliSearch и Scout
Laravel Scout - это популярный пакет, который предоставляет простой и удобный способ добавить полнотекстовый поиск в ваше приложение Laravel. Он...
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
0
10
42
1

Ответы 1

Вероятно, вам придется заменить JOIN подзапросами:

WHERE EXISTS (
  SELECT *
  FROM customers
  WHERE orders.customer_id=customers.customer_id
    AND ...
)

Затем вы можете удалить GROUP BY.

Если вы используете отношения:

$query->whereHas('customers', function($query) {
    $query->where(...)
})

Другие вопросы по теме