Laravel красноречивый: связь «один ко многим» с distinct

#laravel #eloquent #greatest-n-per-group #one-to-many #eloquent-relationship

#laravel #красноречивый #наибольшее число на группу #один ко многим #красноречивый-отношение

Вопрос:

Необходимо получить отдельную строку.

Есть ли какой-либо способ в laravel eloquent избежать дублирования данных. Необходимо получить уникальных пользователей после объединения с таблицей изображений.

Теперь я получаю одних и тех же пользователей, нужно избегать повторения одного и того же пользователя.

Образ модели

 public function user()
{
    return $this->belongsTo('AppUser');
}
  

Таблица пользователя

 id | name
---------
| 1| Joe
| 2| Ben
| 3| Don
  

Таблица изображений

 id  |   name | user_id
---------------------
| 1 |  1.png |    3
| 2 |  2.png |    1
| 3 |  3.png |    1
| 4 |  4.png |    2
  

присоединяйтесь с помощью eloquent :

 Image::with('user')->orderBy('id', 'desc')->paginate(10);
  

Требуемый вывод

 "data": [
    {
        "id": 4,
        "name": "4.png",
        "user_id": 2,
        "user": {
            "id": 2,
            "name": "Ben",
        }
    },
    {
        "id": 3,
        "name": "3.png",
        "user_id": 1,
        "user": {
            "id": 1,
            "name": "Joe",
        }
    },
    {
        "id": 1,
        "name": "1.png",
        "user_id": 3,
        "user": {
            "id": 3,
            "name": "Don",
        }
    },
],
  

Комментарии:

1. на самом деле есть distinct() функция, которую вы можете использовать.

2. @Aless55 Я пробовал разные методы, используя distinct, не работает.

3. Пожалуйста, подумайте, ответьте как принятый или проголосуйте «за» или «против»

Ответ №1:

Похоже, вам нужны все пользователи и только одно из изображений для каждого пользователя. Вы могли бы сделать что-то вроде следующего, чтобы добавить связь изображения с моделью пользователя:

     public function image()
    {
        return $this->hasOne('AppImage')->orderBy('id', 'desc');
    }
  

Затем вы получите доступ к этим данным следующим образом User::has('image')->with('image') ;

Комментарии:

1. Мне нужно сделать distinct для «user_id», есть ли какой-либо способ в laravel eloquent достичь этого?

2. Это почти работает, но я должен получить результат на основе последнего изображения. Делая это по-своему, результат будет зависеть от пользователей. На самом деле в желаемом выводе оно должно быть по убыванию, я это исправил

3. Это должно дать вам последнее изображение для каждого пользователя, я предположил, что вам нужно только одно изображение для каждого пользователя. Это работает у вас сейчас или вам все еще нужна помощь? Не стесняйтесь добавлять свой текущий код, если вам все еще нужна помощь.

Ответ №2:

Чтобы получить уникальные результаты от Eloquent, вызовите метод unique() в конце цепочки методов.

 Image::with('user')
      ->orderBy('id', 'desc') 
      ->paginate(10)
      ->unique() // Like this
  

Если вышеуказанный метод не работает, попробуйте приведенный ниже.

 Image::with('user')
      ->orderBy('id', 'desc') 
      ->paginate(10)
      ->unique()
      ->values()
  

Комментарии:

1. Я добавил еще одну вещь в ответ, теперь попробуйте еще раз.

Ответ №3:

Чтобы получить последнее изображение для каждого пользователя, вы можете использовать самосоединение, например

Схема

 CREATE TABLE users
    (`id` int, `name` varchar(3))
;
    
INSERT INTO users
    (`id`, `name`)
VALUES
    (1, 'Joe'),
    (2, 'Ben'),
    (3, 'Don')
;

CREATE TABLE images
    (`id` int, `name` varchar(5), `user_id` int)
;
    
INSERT INTO images
    (`id`, `name`, `user_id`)
VALUES
    (1, '1.png', 3),
    (2, '2.png', 1),
    (3, '3.png', 1),
    (4, '4.png', 2)
;
  

Запрос

 select a.*, u.*
from images a
left join images b on a.user_id = b.user_id
  and a.id < b.id
join users u on u.id = a.user_id
where b.user_id is null
order by a.id desc
  

Конструктор запросов

 DB::table('images as a')
  ->select('a.*, u.*')
  ->leftJoin('images as b', function ($join) {
        $join->on('a.user_id', '=', 'b.user_id')
             ->whereRaw(DB::raw('a.id < b.id'));
   })
  ->join('users as u', 'u.id', '=', 'a.user_id' )
  ->whereNull('b.user_id')
  ->orderBy('a.id', 'desc')
  ->get();
  

ДЕМОНСТРАЦИЯ