VerbAlexVlad
@VerbAlexVlad
Программист-любитель

Как получить отсортированный массив, если есть distinct?

Добрый день знатоки!=)

Изначально было две проблемы, одну решил.

Подробнее:
Есть таблица "категории" и таблица "продукты"
С помощью связи "один ко многим", делаем жадную загрузку "категорий"

Модель 'Categories':
	public function getProducts () {
		return $this->hasMany(Products::className(), ['category_id' => 'id']);
	}


и выводим всё в контроллере:
Контроллер:
	public function actionView () {
		$query = Categories::find()->select('categories.id');
		$query->innerJoinWith(
			[
				'Products' => function ($query) {
					  $query->select(['products.id', 'products.price']);
					  $query->orderBy(['products.price' => SORT_ASC]);
				},
			]
		);
                debug($query->asArray()->all());
	}

Получим:
Array
(
	[0] => Array
		(
			[id] => 1
			[products] => Array
				(
					[0] => Array
						(
							[id] => 3
							[price] => 100
						)
					[1] => Array
						(
							[id] => 4
							[price] => 50
						)
				)
		)
	[1] => Array
		(
			[id] => 2
			[products] => Array
				(
					[0] => Array
						(
							[id] => 5
							[price] => 300
						)
				)
		)
)


Так вот, первая проблема, если я вызову $query->count(), то он мне покажет не "2", а "3", т.е. сумму всех элементов подмассивов "products". Решил данную проблему добавлением distinct: $query->distinct()->count()

И тут появилась другая проблема. там, где в подмассиве "products" больше одного элемента, мне нужно сортировать их по цене $query->orderBy(['products.price' => SORT_ASC]), но эта запись начинает конфликтовать с distinct
SQLSTATE[HY000]: General error: 3065 Expression #1 of ORDER BY clause is not in SELECT list, references column 'mybd.products.price' which is not in SELECT list; this is incompatible with DISTINCT
The SQL being executed was: SELECT COUNT(*) FROM (SELECT DISTINCT `categories`.`id` FROM `categories` LEFT JOIN `products` ON `categories`.`id` = `products`.`product_id` ORDER BY `products`.`price`) `c`

Как сделать так, чтобы и сортировка работала, и показывал правильное количество элементов в массиве??
Сразу скажу, что count($query) не пойдет, в дальнейшем по этой переменной создается пагинация.
  • Вопрос задан
  • 140 просмотров
Решения вопроса 1
webinar
@webinar Куратор тега Yii
Учим yii: https://youtu.be/-WRMlGHLgRg
А чем Вас не устраивает:
$query = Categories::find()->with('productsByPrice')->all();

и связь:
public function getProductsByPrice () {
		return $this->hasMany(Products::className(), ['category_id' => 'id'])->orderBy('price');
	}

Или если нужны товары, то почему бы не выбирать именно товары?
$query = Products::find()->with('category')->orderBy('price')->all();

или если нужны товары в определенной категории, то
$query = Products::find()->andWhere(['category_id'=>$id])->orderBy('price')->all();

Что Вы получить хотите в итоге?
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
kimono
@kimono
Web developer
Я бы использовал такой запрос:
$rows = Products::find()
->select(['category_id' => 'CAT.id', 'product_id' => 'PROD.id', 'product_price' => 'PROD.price'])
->from(['PROD' => Products::tableName()])
->innerJoin(['CAT' => Categories::tableName()], 'CAT.id = PROD.category_id')
->orderBy(['PROD.price' => SORT_ASC])
->asArray()->all();
$rows = ArrayHelper::index($rows, 'product_id', 'category_id');

На выходе будет примерно такой массив:
[
  1 => [
    177 => ['category_id' => 1, 'product_id' => 177, 'price' => 1000],
    178 => ['category_id' => 1, 'product_id' => 177, 'price' => 2000],
  ],
  2 => [
    179 => ['category_id' => 2, 'product_id' => 179, 'price' => 3000],
    192 => ['category_id' => 2, 'product_id' => 192, 'price' => 4000],
  ],
]


PS: а на ORDER BY у вас ругается потому что вы не джойните, а подгружаете через with. Попробуйте сделать ORDER BY внутри innerJoinWith.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы