【问题标题】:Laravel chunk withcount and whereLaravel 块 withcount 和 where
【发布时间】:2020-05-29 18:09:29
【问题描述】:

我想要一个包含一组选定用户的列表,我可以在其中查看他们从特定日期开始的点击次数。 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
}

但是你会为每个用户遍历所有(几 2-4)百万行,还有其他方法吗?

【问题讨论】:

    标签: mysql laravel eloquent


    【解决方案1】:

    您似乎采取了很多相互矛盾的方法,在我看来,在处理大量数据时,让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 将有每个用户重复点击次数的行,因此我们必须使用 group by 压缩数据。

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

    使用聚合来获取他们的点击量。

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

    这只会填充 users.id 和一个名为 clicks 的字段,其中包含点击量。你应该避免你对块做任何事情。如果设置了外键,这个查询应该会执行得很好。

    完整的查询应该与此类似。由于分组依据,您无法选择额外的字段,但使用聚合函数 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();
    

    【讨论】:

      猜你喜欢
      • 2020-01-30
      • 2017-02-17
      • 1970-01-01
      • 2019-08-06
      • 2019-03-27
      • 2023-03-28
      • 2022-01-01
      • 2017-05-07
      • 2022-12-26
      相关资源
      最近更新 更多