Как использовать GroupBy во вложенном запросе в Laravel 5?

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

Вот детали структуры таблицы:

Packages: id, title
Fixtures: id, package_id, name
Deals: id, discound, description
Fixtures_Deal: id, fixture_id, deal_id, price

Мне нужно получить список пакетов вместе с минимальной ценой сделки, которая предлагается в каждом приборе для каждого пакета.

Вот запрос mysql, который я выполняю в phpMyAdmin или SQLYog, и он отлично работает, но в Laravel выдает ошибку «p.title ‘not in GROUP BY».

SELECT
p.title AS package_title,
tbl_min_value.min_price AS min_price
FROM
(SELECT
fixture_id,
MIN(deal_price) AS min_price
FROM
fixture_deal
GROUP BY fixture_id) AS tbl_min_value
JOIN fixtures AS f
ON f.id = tbl_min_value.fixture_id
RIGHT JOIN packages AS p
ON f.package_id = p.id
GROUP BY p.id

Кстати, я пытаюсь добиться этого с помощью следующего метода в модели:

return DB::statement('SELECT
p.title AS package_title,
tbl_min_value.min_price AS min_price
FROM
(SELECT
fixture_id,
MIN(deal_price) AS min_price
FROM
fixture_deal
GROUP BY fixture_id) AS tbl_min_value
JOIN fixtures AS f
ON f.id = tbl_min_value.fixture_id
RIGHT JOIN packages AS p
ON f.package_id = p.id
GROUP BY p.id');

4

Решение

Я нашел другой способ использования Eloquent Collection mapWithKeys метод.

https://laravel.com/docs/5.3/collections#method-mapwithkeys

Поэтому я получил данные двух запросов по отдельности и сопоставил обе коллекции с ключами в один объект коллекции.

Образец кода:

$packages = Package::getPackages();

$deal_min_price = Deal::getMinimumPrice();

$packages_with_price = $packages->mapWithKeys(function ($packages) use ($deal_min_price) {
return $packages['price'] => $deal_min_price['min_price'];
});

Вы можете использовать foreach цикл внутри mapWithKey's closure,

2

Другие решения

Ошибка, которую вы получаете, заключается в том, что MySQL 5.7 стал более совместимым с SQL99. Вы можете прочитать немного об этом Вот, но он включает в себя настройку режима SQL под названием ONLY_FULL_GROUP_BY что гарантирует, что любые неагрегированные столбцы будут выбраны внутри GROUP BY, Что это значит для вашей ситуации?

Ну просто нужно добавить p.title а также tbl_min_value.min_price чтобы группа работала правильно, так как они не агрегированы:

GROUP BY p.id, p.title, tbl_min_value.min_price

Вы можете быть удивлены: «С какой стати они это делают?». Ну, используя GROUP BYдо того, как было легко случайно «свернуть» данные, где строка имела более одного возможного значения, которое она могла отобразить, поэтому она просто показывала первое. Это заставляет вас выяснить, что вы хотите показать, используя агрегатную функцию, такую ​​как MIN() или же MAX()или добавьте его в группу, указав, что вы хотите, чтобы они были разделены.

Если вам не нравится, как это работает, вы можете временно отключить его, выполнив следующее:

# Run this query and copy the values
SELECT @@sql_mode;

# Remove "ONLY_FULL_GROUP_BY" and paste it in here where the XXX is
SET sql_mode = 'XXX';

Или вы можете сделать это изменение постоянным, отредактировав my.cnf файл под [mysqld] раздел, как это, где XXX является выводом SELECT @@sql_mode; минус ONLY_FULL_GROUP_BY часть:

[mysqld]
sql_mode=XXX
1

Странно, что SQL-запрос работает нормально в phpMyAdmin, но тот же не работает в Laravel 5.3. Не могли бы вы опубликовать структуру БД с примерами данных, чтобы мы посмотрели?

Кстати, я пытался следовать SQL и работает нормально в Laravel 5.2:

SELECT
p.title AS package_title,
tbl_min_value.min_price AS min_price
FROM
(SELECT
fixture_id,
MIN(deal_price) AS min_price
FROM
fixtures_deal
GROUP BY fixture_id) AS tbl_min_value
JOIN fixtures AS f
ON f.id = tbl_min_value.fixture_id
RIGHT JOIN packages AS p
ON f.package_id = p.id
GROUP BY p.id
0
По вопросам рекламы [email protected]