Когда я использую db raw, он работает
Мой запрос использует db raw следующим образом:
$products = DB::select(DB::raw('SELECT * FROM ( SELECT a.*, b.name AS store_name, b.address FROM products a JOIN stores b ON b.id = a.store_id WHERE a.category_id = '.$category_id.' ORDER BY a.total_sold DESC, a.updated_at DESC LIMIT '.$num.' ) AS product GROUP BY store_id'));
Оно работает. Но я хочу изменить его, используя laravel eloquent
Я пробую вот так:
$products = Product::where('category_id', '=', $category_id) ->with('store') ->groupBy('store_id') ->orderBy('total_sold','desc') ->orderBy('updated_at', 'desc') ->take($num) ->get();
по$products = Product::where('category_id', '=', $category_id) ->with('store') ->groupBy('store_id') ->orderBy('total_sold','desc') ->orderBy('updated_at', 'desc') ->take($num) ->get();
Он также работает. Но orderBy updated_at не выполнен
Как я могу это решить?
Мне кажется, что вы используете группу неправильно. Даже если вы получили правильные результаты для запроса, прежде чем он обратится ко мне, что это случайно. Группу следует использовать для агрегирования результатов запроса и получения агрегированных значений столбцов. Выбирая столбцы, которые на самом деле не агрегированы, могут быть опасны при неправильном использовании.
Из документов Mysql для версии 5.6:
MySQL расширяет стандартное использование SQL GROUP BY, чтобы список выбора мог ссылаться на неагрегированные столбцы, не названные в предложении GROUP BY. Это означает, что предыдущий запрос является законным в MySQL. Вы можете использовать эту функцию для повышения производительности, избегая ненужной сортировки и группировки столбцов. Однако это полезно, прежде всего, когда все значения в каждом неагрегированном столбце, не названном в GROUP BY, одинаковы для каждой группы. Сервер может выбирать любое значение из каждой группы, поэтому, если они не совпадают, выбранные значения являются неопределенными. Более того, выбор значений из каждой группы не может зависеть от добавления предложения ORDER BY. Сортировка набора результатов происходит после того, как были выбраны значения, и ORDER BY не влияет на значения в каждой группе, которую выбирает сервер.
Кроме того, по состоянию на MySql 5.7.5 по умолчанию SQL-режим включает флаг ONLY_FULL_GROUP_BY, который будет:
Отклонить запросы, для которых список выбора, условие HAVING или ORDER BY относятся к неагрегированным столбцам, которые не имеют ни имени в предложении GROUP BY, ни функционально зависят от столбцов GROUP BY (уникально определенных).
В образовательных целях вы должны быть способны точно так же точно получить такой же запрос с Laravel (непроверенный и без использования псевдонимов таблицы), но я бы не стал использовать его:
$subQuery = Products::selectRaw('products.*, stores.name as store_name, stores.address') ->join('stores', 'stores.id', '=', 'products.store_id') ->where('products.category_id', '=', $category_id) ->orderBy('products.total_sold', 'DESC') ->orderBy('products.updated_at', 'DESC') ->take($num) $products = DB::table(DB::raw('(' . $subQuery->toSql() . ') t')) ->groupBy('store_id') ->setBindings($subQuery->getBindings()) ->get();
Но для меня кажется, что вы пытаетесь сделать все магазины вместе с продуктами в нужной вам категории. Таким образом, большинство решений Laravel, вероятно, будет выглядеть примерно так:
Stores::with(['products' => function($productsQuery) use ($category_id) { // This limits all the retrieved products to the provided category $productsQuery ->where('category_id', '=', $category_id) ->orderBy('total_sold', 'DESC') ->orderBy('updated_at', 'DESC'); }])->whereHas('products', function($productsQuery) use ($category_id) { // This makes sure that the store actually has at least one product from the category $productsQuery->where('category_id', '=', $category_id); })->get();
Возможно, я сделал неверные предположения, посмотрев на ваш запрос, но на данный момент это не имеет особого смысла … Я бы начал оттуда в любом случае.