我试图从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
}
}
它解决了太多查询的问题,但需要花费很多时间。是否可以更快地做同样的事情?
答案 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
}
}