Страница 1 из 1

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

Добавлено: 2020.05.01, 21:36
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 айдишников разных категорий, надо чтобы выборка была по одной записи с каждой категории
Как это сделать?

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

Добавлено: 2020.05.03, 01:12
samdark
А как бы вы это сделали в SQL?

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

Добавлено: 2020.05.03, 13:35
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)
Но я не уверен что это самый оптимальный вариант

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

Добавлено: 2020.05.03, 16:23
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();
Я бы сделал так, не знаю, верно или нет, просто может помогу чем-то или идею подам

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

Добавлено: 2020.05.03, 17:41
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
Но спасибо попробую поиграть с ним

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

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

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

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

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

Добавлено: 2020.05.04, 09:29
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.* и должно работать

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

Добавлено: 2020.05.04, 10:01
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

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

Добавлено: 2020.05.05, 09:00
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();

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

Добавлено: 2020.05.06, 20:24
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

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

Добавлено: 2020.05.07, 07:29
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

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

Добавлено: 2020.05.07, 21:10
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
)

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

Добавлено: 2020.05.08, 10:00
gerzog1995
скинь пожалуйста структуру бд с таблицами для запроса

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

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

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

Добавлено: 2020.05.17, 13:13
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();

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

Добавлено: 2020.05.20, 20:05
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();
Спасибо, попробую