Как правильно построить запрос в yii2, чтобы с каждой категории бралось по одной записи?

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
alexa777
Сообщения: 299
Зарегистрирован: 2016.03.01, 17:38

Как правильно построить запрос в yii2, чтобы с каждой категории бралось по одной записи?

Сообщение alexa777 »

Вот запрос:

Код: Выделить всё

$query = self::find()->select('id, title, url, img, img_thumb, category_id')
->where(['status' => 1])
 ->andWhere(['in', 'category_id', $array_category_id])
 ->orderBy(new Expression('rand()'))
 ->limit(10)
 ->asArray()->all();

$array_category_id - здесь 10 айдишников разных категорий, надо чтобы выборка была по одной записи с каждой категории
Как это сделать?

Аватара пользователя
samdark
Администратор
Сообщения: 9296
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: Как правильно построить запрос в yii2, чтобы с каждой категории бралось по одной записи?

Сообщение samdark »

А как бы вы это сделали в SQL?

alexa777
Сообщения: 299
Зарегистрирован: 2016.03.01, 17:38

Re: Как правильно построить запрос в yii2, чтобы с каждой категории бралось по одной записи?

Сообщение alexa777 »

samdark писал(а):
2020.05.03, 01:12
А как бы вы это сделали в SQL?
В SQL у меня получилось только так через временную таблицу

Код: Выделить всё

create TEMPORARY TABLE ids(id int);
insert into ids(id)
select (select id from news n2 where n2.category_id = n1.category_id order by rand() limit 1)
	from news n1
	where category_id in (1,2,3)
	and status =1 
	group by category_id;
select * from news where id in (select * from ids)
Но я не уверен что это самый оптимальный вариант

gerzog1995
Сообщения: 24
Зарегистрирован: 2018.07.29, 21:07

Re: Как правильно построить запрос в yii2, чтобы с каждой категории бралось по одной записи?

Сообщение gerzog1995 »

Код: Выделить всё

Category::find()->from(Category::find()->select('category.id AS cid, news.id AS nid, news.text,news.title, news.url, news.img, news.img_thumb, news.category_id')
            ->innerJoin('news as n', 'category.id = n.category_id')->orderBy('rand()'))
            ->where(['status' => 1])
            ->andWhere(['cid' => $array_category_id])
            ->groupBy('cid')->asArray()->all();
Я бы сделал так, не знаю, верно или нет, просто может помогу чем-то или идею подам

alexa777
Сообщения: 299
Зарегистрирован: 2016.03.01, 17:38

Re: Как правильно построить запрос в yii2, чтобы с каждой категории бралось по одной записи?

Сообщение alexa777 »

gerzog1995 писал(а):
2020.05.03, 16:23

Код: Выделить всё

Category::find()->from(Category::find()->select('category.id AS cid, news.id AS nid, news.text,news.title, news.url, news.img, news.img_thumb, news.category_id')
            ->innerJoin('news as n', 'category.id = n.category_id')->orderBy('rand()'))
            ->where(['status' => 1])
            ->andWhere(['cid' => $array_category_id])
            ->groupBy('cid')->asArray()->all();
Я бы сделал так, не знаю, верно или нет, просто может помогу чем-то или идею подам
Сходу попробовал, не получилось, выдало ошибку

Код: Выделить всё

PDOException: SQLSTATE[42S22]: Column not found: 1054 Unknown column 'news.id' in 'field list' i
Но спасибо попробую поиграть с ним

gerzog1995
Сообщения: 24
Зарегистрирован: 2018.07.29, 21:07

Re: Как правильно построить запрос в yii2, чтобы с каждой категории бралось по одной записи?

Сообщение gerzog1995 »

Я таблицы заменил, не знаю какие у вас там, перепишите под свои таблицы и должно в итоге получится то, что вы хотите.

alexa777
Сообщения: 299
Зарегистрирован: 2016.03.01, 17:38

Re: Как правильно построить запрос в yii2, чтобы с каждой категории бралось по одной записи?

Сообщение alexa777 »

gerzog1995 писал(а):
2020.05.03, 17:49
Я таблицы заменил, не знаю какие у вас там, перепишите под свои таблицы и должно в итоге получится то, что вы хотите.
у меня они и есть category и news

gerzog1995
Сообщения: 24
Зарегистрирован: 2018.07.29, 21:07

Re: Как правильно построить запрос в yii2, чтобы с каждой категории бралось по одной записи?

Сообщение gerzog1995 »

from(Category::find()->select('category.id AS cid, news.id AS nid, n.text,n.title, n.url,n.img, n.img_thumb, n.category_id')
Замените news.* на псевдоназвание n.* и должно работать

alexa777
Сообщения: 299
Зарегистрирован: 2016.03.01, 17:38

Re: Как правильно построить запрос в yii2, чтобы с каждой категории бралось по одной записи?

Сообщение alexa777 »

gerzog1995 писал(а):
2020.05.04, 09:29
from(Category::find()->select('category.id AS cid, news.id AS nid, n.text,n.title, n.url,n.img, n.img_thumb, n.category_id')
Замените news.* на псевдоназвание n.* и должно работать
попробовал

Код: Выделить всё

PDOException: SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column '0.nid' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

unknownby
Сообщения: 344
Зарегистрирован: 2019.11.05, 16:34
Контактная информация:

Re: Как правильно построить запрос в yii2, чтобы с каждой категории бралось по одной записи?

Сообщение unknownby »

Попробуй так, а то у тебя два раза ругается на твой 'news.id' или '0.nid'

Код: Выделить всё

Category::find()->from(Category::find()->select('category.id AS cid, n.*')
            ->innerJoin('news as n', 'category.id = n.category_id')->orderBy('rand()'))
            ->where(['status' => 1])
            ->andWhere(['cid' => $array_category_id])
            ->groupBy('cid')->asArray()->all();

alexa777
Сообщения: 299
Зарегистрирован: 2016.03.01, 17:38

Re: Как правильно построить запрос в yii2, чтобы с каждой категории бралось по одной записи?

Сообщение alexa777 »

unknownby писал(а):
2020.05.05, 09:00
Попробуй так, а то у тебя два раза ругается на твой 'news.id' или '0.nid'

Код: Выделить всё

Category::find()->from(Category::find()->select('category.id AS cid, n.*')
            ->innerJoin('news as n', 'category.id = n.category_id')->orderBy('rand()'))
            ->where(['status' => 1])
            ->andWhere(['cid' => $array_category_id])
            ->groupBy('cid')->asArray()->all();
Тожке ошибка

Код: Выделить всё

SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column '0.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by

unknownby
Сообщения: 344
Зарегистрирован: 2019.11.05, 16:34
Контактная информация:

Re: Как правильно построить запрос в yii2, чтобы с каждой категории бралось по одной записи?

Сообщение unknownby »

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

P.S.
alexa777 писал(а):
2020.05.01, 21:36
$array_category_id - здесь 10 айдишников разных категорий, надо чтобы выборка была по одной записи с каждой категории
Как это сделать?
Ну так ответ лежит на поверхности. Во-1 имеется уже 10 РАЗНЫХ идентификаторов категорий. А следовательно нужно вывести что-то из новостей, где присутствует данный category_id в категории.

Код: Выделить всё

$query = News::find()
	->andWhere(['in', 'category_id', $array_category_id])
	->groupBy('category_id')
	->orderBy(new Expression('rand()'))
	->all();
А если нужно что-то вывести из самой таблицы категорий, то первый запрос должен работать, можно убрать даже limit(10), если всегда будет передаваться по 10 штук category_id

alexa777
Сообщения: 299
Зарегистрирован: 2016.03.01, 17:38

Re: Как правильно построить запрос в yii2, чтобы с каждой категории бралось по одной записи?

Сообщение alexa777 »

unknownby писал(а):
2020.05.07, 07:29
Можно ли как-то узнать, что есть в системе и что предполагается сделать?
Может есть более деликатный способ, чем делать непонятной конструкции запрос.

P.S.
alexa777 писал(а):
2020.05.01, 21:36
$array_category_id - здесь 10 айдишников разных категорий, надо чтобы выборка была по одной записи с каждой категории
Как это сделать?
Ну так ответ лежит на поверхности. Во-1 имеется уже 10 РАЗНЫХ идентификаторов категорий. А следовательно нужно вывести что-то из новостей, где присутствует данный category_id в категории.

Код: Выделить всё

$query = News::find()
	->andWhere(['in', 'category_id', $array_category_id])
	->groupBy('category_id')
	->orderBy(new Expression('rand()'))
	->all();
А если нужно что-то вывести из самой таблицы категорий, то первый запрос должен работать, можно убрать даже limit(10), если всегда будет передаваться по 10 штук category_id

Такой запрос я сразу пробовал, не работает, groupBy требует агрегатную функцию
SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'base.news.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
The SQL being executed was: SELECT * FROM `news` WHERE `category_id` IN ('13', '8', '3', '10', '9', '11', '12', '14', '15', '17') GROUP BY `category_id` ORDER BY rand()

Error Info: Array
(
[0] => 42000
[1] => 1055
[2] => Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'base.news.id' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
)

gerzog1995
Сообщения: 24
Зарегистрирован: 2018.07.29, 21:07

Re: Как правильно построить запрос в yii2, чтобы с каждой категории бралось по одной записи?

Сообщение gerzog1995 »

скинь пожалуйста структуру бд с таблицами для запроса

alexa777
Сообщения: 299
Зарегистрирован: 2016.03.01, 17:38

Re: Как правильно построить запрос в yii2, чтобы с каждой категории бралось по одной записи?

Сообщение alexa777 »

gerzog1995 писал(а):
2020.05.08, 10:00
скинь пожалуйста структуру бд с таблицами для запроса
База category - id | name
База news - id | title | url | img | img_thumb | category_id

lavros
Сообщения: 12
Зарегистрирован: 2017.01.13, 08:54

Re: Как правильно построить запрос в yii2, чтобы с каждой категории бралось по одной записи?

Сообщение lavros »

Можно сделать через подзапрос:

Код: Выделить всё

SELECT *
FROM news
WHERE
    id IN (
        SELECT MAX(id)
        FROM news
        WHERE category_id IN (13, 8, 3, 10, 9, 11, 12, 14, 15, 17)
        GROUP BY category_id
    )
В подзапросе используем MAX(id) чтобы при группировке по category_id не получить ошибку группировки данных: 1055 Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column...
По сути, получилось что мы получим последние новости в этих категориях.

Код: Выделить всё

$subQuery = self::find()
    ->select(new Expression('MAX(id)'))
    ->where(['category_id' => $array_category_id])
    ->groupBy('category_id');

$query = self::find()
    ->select('id, title, url, img, img_thumb, category_id')
    ->where(['in', 'id', $subQuery])
    ->andWhere(['status' => 1])
    ->orderBy(new Expression('rand()'))
    ->asArray()
    ->all();

alexa777
Сообщения: 299
Зарегистрирован: 2016.03.01, 17:38

Re: Как правильно построить запрос в yii2, чтобы с каждой категории бралось по одной записи?

Сообщение alexa777 »

lavros писал(а):
2020.05.17, 13:13
Можно сделать через подзапрос:

Код: Выделить всё

SELECT *
FROM news
WHERE
    id IN (
        SELECT MAX(id)
        FROM news
        WHERE category_id IN (13, 8, 3, 10, 9, 11, 12, 14, 15, 17)
        GROUP BY category_id
    )
В подзапросе используем MAX(id) чтобы при группировке по category_id не получить ошибку группировки данных: 1055 Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column...
По сути, получилось что мы получим последние новости в этих категориях.

Код: Выделить всё

$subQuery = self::find()
    ->select(new Expression('MAX(id)'))
    ->where(['category_id' => $array_category_id])
    ->groupBy('category_id');

$query = self::find()
    ->select('id, title, url, img, img_thumb, category_id')
    ->where(['in', 'id', $subQuery])
    ->andWhere(['status' => 1])
    ->orderBy(new Expression('rand()'))
    ->asArray()
    ->all();
Спасибо, попробую

Ответить