【问题标题】:Fetch users who have posted the last comment 3 days before eloquent获取 eloquent 前 3 天发表最后一条评论的用户
【发布时间】:2018-03-16 18:50:02
【问题描述】:

实际上,我需要在一个时间间隔内向我的所有用户发送提醒邮件。所以基本上如果用户在过去 3 天内没有发表任何评论,我需要向他发送电子邮件。

我正在使用表结构:

用户

  • 身份证
  • 用户名
  • 电子邮件
  • 退订

评论

  • 身份证
  • user_id
  • 评论
  • created_at

我为此使用了愚蠢的查询

Comment::with(['user' => function ($q) {
        $q->where('unsubscribed', 0)->select('id', 'username', 'email');
    }])
->groupBy('user_id')
->whereDate('created_at', $thereDaysAgoDate)
->get(['user_id']);

这给了我在该特定日期发表评论的所有用户。

我的问题是,I only want the users who have posted a comment on that particular date but then not posted any comment after that date

我可以通过从comment 表中获取所有用户,然后通过 PHP 比较日期,如果其他条件,但我不想以这种方式接近。

那么有什么方法可以仅通过 eloquent 来实现。

【问题讨论】:

    标签: php mysql laravel eloquent


    【解决方案1】:

    您可以将whereHaswhereDoesntHave组合起来,也可以翻转查询,按照关系满足的条件过滤用户

        $the_date = '2017-09-29';
        User::where('unsubscribed', 0)->whereHas('comments', function ($comments)  use ($the_date){
            return $comments->whereDate('created_at', '=', $the_date);
        })->whereDoesntHave('comments',  function($comments) use ($the_date){
            return $comments->whereDate('created_at', '>', $the_date);
        })->get();
    

    PS:我假设您与用户有comments 关系。这是在 L5.5 上测试的。*

    【讨论】:

    • 这段代码生成了多少个查询?如果它只运行一个查询看起来不错!
    • 它应该只使用带有子查询的existsnot exists sql 条件运行单个查询。您可以通过将->get() 更改为->toSql() 来自行检查
    • 这太棒了伙计 :) 它创建了总共 3 个子查询的查询,这不是它的工作准确的问题 :)
    【解决方案2】:
      $main_query =  Comment::with(['user' => function ($q) {
                    $q->where('unsubscribed', 0)->select('id', 'username', 'email');
                }])
            ->groupBy('user_id');     
    
      $all_users = $main_query->whereDate('created_at', $thereDaysAgoDate)
            ->get(['user_id']);
    
      $users_who_have_posts_after = $main_query->
            ->whereDate('created_at','>', $thereDaysAgoDate)
            ->get(['user_id']);
    
      $users_without_post_after = $all_users->whereNotIn('user_id',$users_who_has_posts_after);
    

    也许这不是最好的方法,但它只执行 2 个查询和一个循环。 我正在获取在所需日期发布的所有用户,然后获取在我们的日期之后仍然发布的用户,然后将原始用户池与仍然活跃的用户进行比较。

    【讨论】:

    • 好技巧加一个 :) 但我认为单个查询也可以。希望我能得到任何具体的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-03
    • 1970-01-01
    • 2015-04-17
    • 1970-01-01
    相关资源
    最近更新 更多