Laravel кусок с учетом и где - PullRequest
2 голосов
/ 14 февраля 2020

Мне нужен список с выбранной группой пользователей, где я могу видеть, сколько кликов у них есть, начиная с указанной даты c. Clicks - это таблица с несколькими миллионами строк, для меня сладким местом было значение от 250 000 до 500 000 в качестве значения чанка. (Этот SQL запрос занял 2,4 секунды)

SELECT c.user_id, u.name, count(*) as aantal 
from clicks c
    join users u on c.user_id = u.id
where c.updated_at > '2020/02/09 20:00' and c.user_id not in (1, 3, 16, 18, 19, 20)
GROUP BY user_id;

Для всех кликов на пользователя этот запрос работает:

$users= User::has('clicks')
->withCount('clicks')
->orderBy('clicks_count', 'desc')
->get()
->whereNotIn('id', [1, 3, 16, 18, 19, 20])
->transform(function ($item) {
    // Remove all fields that you don't use inside the view
    unset($item->created_at, $item->updated_at, $item->admin, $item->email_verified_at);
    return $item;
});

Для получения общего количества кликов я нашел это:

$count = 0;
Click::chunk(500000, function($clicks) use (&$count)
{
    $count = $count + count($clicks);
});

Я пробовал некоторые запросы, но пока ничего не получалось.

Я думал о чем-то вроде:

$users = User::whereNotIn('id', [1, 3, 16, 18, 19, 20])->get();

foreach ($users as $user) {
    // Here find all CLicks for this user with later then a date with a Chunk
}

Но тогда вы бы go прошли через все ( несколько 2-4) миллионы строк для каждого пользователя, есть ли другой способ?

1 Ответ

0 голосов
/ 14 февраля 2020

Вы, похоже, go много противоречивых подходов, по моему мнению, когда имеете дело с большими объемами данных, пусть sql делает как можно больше В следующем запросе вы получите все необходимые данные.

Users::join('clicks', 'clicks.user_id', '=', 'u.id')->where('clicks.updated_at', '>', '2020/02/09 20:00')->whereNotIn('users.id', [1, 3, 16, 18, 19, 20]);

Когда вы присоединяете данные таким образом, sql будет повторять строки с каждым пользователем столько раз, сколько у них будет кликов, поэтому мы должны отказаться sh данные возвращаются с группировкой по.

...->groupBy('users.id');

Используйте агрегат, чтобы получить количество кликов, которое у них есть.

...->select('users.id', DB::raw('count(clicks.id) as clicks'));

Это заполнит только users.id и a поле называется clickks с количеством кликов. Ты должен избегать того, чтобы ты что-то делал с куском. Если внешние ключи настроены, этот запрос должен работать хорошо.

Полный запрос должен выглядеть примерно так. Вы не можете выбрать дополнительные поля из-за группы, но используя функцию агрегатов max или min, вы можете обойти это.

Users::join('clicks', 'clicks.user_id', '=', 'u.id')
    ->where('clicks.updated_at', '>', '2020/02/09 20:00')
    ->whereNotIn('users.id', [1, 3, 16, 18, 19, 20])
    ->groupBy('users.id')
    ->select('users.id', DB::raw('count(clicks.id) as clicks'))
    ->get();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...