【问题标题】:Laravel Eloquent limit() and count() returns full countLaravel Eloquent limit() 和 count() 返回完整计数
【发布时间】:2021-07-16 14:35:47
【问题描述】:

我需要对最新的 1000 条记录使用count() 方法。

例如,我们有 3 个用户:

  • 拥有 900 条记录的用户 A
  • 拥有 20.000 条记录的用户 B
  • 用户 C 有 10 条记录

现在我想只考虑最近的 1000 条记录进行计算,这意味着用户 A 和 C 将使用他们的所有记录,因为

// This should return for User A and C, 900 and 10, but for User C 1000
$recent_activities = Activity::select('id', 'user_id', 'activity')->where('user_id', $user->id)
->latest('id')->limit(1000)->count();



// The next 3 queries should analyse the recent 1000 records for occurences of certain %like% records and count them
$result_chat_refunds = Activity::where('activity', 'like', 'Credits erstattet%')->where('user_id', $user->id)
->latest('id')->limit(1000)->count();

$result_credit_membership = Activity::where('activity', 'like', '%Membership gutgeschrieben%')->where('user_id', $user->id)
->latest('id')->limit(1000)->count();

$result_credit_credits = Activity::where('activity', 'like', '%Credits gutgeschrieben%')->where('user_id', $user->id)
->latest('id')->limit(1000)->count();

我怎样才能做到这一点?

【问题讨论】:

    标签: sql eloquent


    【解决方案1】:

    这是一个简单的解决方案,它并没有真正使用 eloquent 的任何其他工具。

    似乎工作得很好,性能也很棒。

    $combined_array = array();
    
    $recent_activities = Activity::select('id', 'user_id', 'activity')->where('user_id', $user->id)
    ->latest('id')->limit(1000)->get();
    
    $combined_array['number_total'] = count($recent_activities);
    $count_chat_refunds = 0;
    $count_credit_membership = 0;
    $count_credit_credits = 0;
    foreach($recent_activities as $cr) {
        if (str_starts_with($cr->activity, "Credits erstattet")) {
            $count_chat_refunds += 1;
        } else if (str_contains($cr->activity, "Membership gutgeschrieben")) {
            $count_credit_membership += 1;
        } else if (str_contains($cr->activity, "Credits gutgeschrieben")) {
            $count_credit_credits += 1;
        }
    }
    
    $combined_array['number_chat_refunds'] = $count_chat_refunds;
    $combined_array['number_credit_membership'] = $count_credit_membership;
    $combined_array['number_credit_credits'] = $count_credit_credits;
    

    【讨论】:

      【解决方案2】:

      也许是这样的修改:

       SELECT TOP 1000 X, 
              COUNT(X) OVER() AS Y
       FROM TblZ
       WHERE Criteria ='Whatever'
       ORDER BY ID DESC
      

      IDK 我没有测试这个所以不要开枪。

      【讨论】:

        【解决方案3】:

        第一次没有正确理解问题:

        $recentActivities = Activity::select('id')->where('user_id', $user->id)->latest('id')->limit(1000);
        
        $resultChatRefunds = Activity::where('activity', 'like', 'Credits erstattet%')->whereIn('id', $recentActivities)->count();
        $resultCreditMembership = Activity::where('activity', 'like', '%Membership gutgeschrieben%')->whereIn('id', $recentActivities)->count();
        $resultCreditCredits = Activity::where('activity', 'like', '%Credits gutgeschrieben%')->whereIn('id', $recentActivities)->count();
        

        请注意,限制与计数在数据库中的工作方式与您的结果一样:

        https://www.db-fiddle.com/f/tWDPuHtJsxiFYRv3XEFwH5/0

        因为SELECT语句在LIMIT之前运行,所以DB先统计记录,然后限制为1000,但是统计后你有一条记录,所以没有什么限制。

        【讨论】:

        • 这是错误的。如果用户 C 完成的其中一些活动低于他最后 1000 次,那么它们仍然会被计算在内。
        • 哦,很抱歉。我没有正确理解这个问题。现在检查一下,我添加了另一个解决方案。
        猜你喜欢
        • 2017-07-23
        • 2014-07-04
        • 2015-01-29
        • 2016-12-07
        • 2016-02-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-08
        相关资源
        最近更新 更多