Laravel 4.2日期范围内的多个查询

时间:2016-05-05 16:15:55

标签: mysql sql laravel laravel-4 eloquent

我试图从3个表中获取每个日期的数据:使用hasMany方法与其他2个表连接的主表。

数据存储如例:

主表:

id | article title |        url      | created_at | updated_at |
----------------------------------------------------------------
14  | Some Title    | www.example.com | TIMESTAMP  | TIMESTAMP  |

视图表(每小时有写入的视图数):

id | article_id | views | created_at | updated_at |
---------------------------------------------------
1  |     14     |  317  | TIMESTAMP  | TIMESTAMP  | (01:00:00)
2  |     14     |  186  | TIMESTAMP  | TIMESTAMP  | (02:00:00)

点击表(每篇文章都写有这篇文章):

id | article_id |  ip_adress  | created_at | updated_at |
---------------------------------------------------------
1  |     14     | 192.168.1.1 | TIMESTAMP  | TIMESTAMP  |

例如:

我需要收到2016年2月1日至2016年3月1日的文章。 对于每篇文章,我需要对每天的观看次数和点击次数进行总结。 所以在结果中我需要得到这样的东西:

ID: 14, Title: Some Title, Views: 503, Clicks: 27

首先,我编写了这段代码,但它向数据库发出了很多请求:

$dates = new DatePeriod($start, new DateInterval('P1D'), $stop);

foreach ($dates as $i => $date) {
    $articles = Articles::with(['views' => function ($query) use ($date) {
        $query->where('created_at', $date);
    }, 'clicks' => function ($query) use ($date) {
        $query->where('created_at', $date);
    }])->get();

    foreach ($articles as $article) {
      foreach ($views->countOfViews as $i) {
        // Code
      }
      foreach ($clicks->countOfClicks as $i) {
        // Code
      }
      // Code
    }
}

然后我找到了解决方案,以获得与我在第一个示例中获得完全相同的结果,但仅提出三个请求:

$dates = new DatePeriod($start, new DateInterval('P1D'), $stop);
$articles = Articles::with(['views' => function ($query) use ($start, $stop) {
    $query->whereBetween('created_at', array($start, $stop));
  }, 'clicks' => function ($query) use ($start, $stop) {
    $query->whereBetween('created_at', array($start, $stop));
  }])->get();

foreach ($dates as $date) {
  foreach ($articles as $article) {
    foreach ($views->countOfViews as $i) if ($date->format('Y-m-d') === $i->created_at->toDateString()) {
      // Code
    }
    foreach ($clicks->countOfClicks as $i) if ($date->format('Y-m-d') === $i->created_at->toDateString()) {
      // Code
    }
    // Code
  }
}

它解决了太多查询的问题,但需要花费很多时间。是否可以更快地做同样的事情?

1 个答案:

答案 0 :(得分:0)

最终代码:

$dates = new DatePeriod($start, new DateInterval('P1D'), $stop);
$articles = Articles::with(['views' => function ($query) use ($start,         $stop) {
    $query->whereBetween('created_at', array($start, $stop))
          ->groupBy('campaign_id', DB::raw('DATE(created_at)'))
          ->selectRaw('*, sum(views) as views');
  }, 'clicks' => function ($query) use ($start, $stop) {
    $query->whereBetween('created_at', array($start, $stop))
          ->groupBy('campaign_id', DB::raw('DATE(created_at)'))
          ->selectRaw('*, sum(clicks) as clicks');
  }])->get();

foreach ($dates as $date) {
  foreach ($articles as $article) {
    foreach ($views->countOfViews as $i) if ($date->format('Y-m-d') === $i->created_at->toDateString()) {
      // Code
    }
    foreach ($clicks->countOfClicks as $i) if ($date->format('Y-m-d') === $i->created_at->toDateString()) {
      // Code
    }
    // Code
  }
}