如何从laravel 5.1中的数据库表的created_at属性中选择年份和月份?

Paw*_*gol 15 php sql laravel eloquent laravel-5.1

我的问题是我想从created_at每年和每月的属性中获取数据库表中的数据.我试过的代码是:

$post= Mjblog::select(DB::raw('YEAR(created_at) year, MONTH(created_at) month'));
$posts_by_y_m = $post->where('created_at',$post)->get();
Run Code Online (Sandbox Code Playgroud)

Mar*_*ean 51

查询构建器中提供了日期帮助程序:

$post = Mjblog::whereYear('created_at', '=', $year)
              ->whereMonth('created_at', '=', $month)
              ->get();
Run Code Online (Sandbox Code Playgroud)

  • 你也可以使用 `->whereMonth('created_at', $month)`。两者都会起作用。 (2认同)

M K*_*aid 12

性能评估

虽然接受的答案可能会解决OP问题,但这并不是数据库性能方面的最佳解决方案。因为当应用whereYear()whereMonth()helper 来查询记录时,它使得查询不可SARGable。这意味着如果比较列created_at在数据库中建立了索引,则在搜索数据时将忽略该索引。看What makes a SQL statement sargable?

考虑以下表达式

$posts = Mjblog::whereYear('created_at', '=', $year)
               ->whereMonth('created_at', '=', $month)
               ->get();
Run Code Online (Sandbox Code Playgroud)

结果查询将类似于

select * 
from mjblog 
where year(`created_at`) = :year 
  and month(`created_at`) = :month
Run Code Online (Sandbox Code Playgroud)

上面的查询可以清楚地视为不可控制的,因为应用了year()和函数来生成非索引值。month()created_at

为了使其成为 SARGable 表达式,最好在比较索引列时定义值的精确/范围。与 OP 一样,范围可以从月份和年份值得出,如下所示

$year = 2000;
$month = 2;
$date = \Carbon\Carbon::parse($year."-".$month."-01"); // universal truth month's first day is 1
$start = $date->startOfMonth()->format('Y-m-d H:i:s'); // 2000-02-01 00:00:00
$end = $date->endOfMonth()->format('Y-m-d H:i:s'); // 2000-02-29 23:59:59
Run Code Online (Sandbox Code Playgroud)

现在 SARGable 表达式可以写为


select * 
from mjblog 
where created_at between :start and :end
Run Code Online (Sandbox Code Playgroud)

或者

select * 
from mjblog 
where created_at >= :start 
  and created_at <= :end
Run Code Online (Sandbox Code Playgroud)

在查询构建器中,它可以表示为


$posts = Mjblog::whereBetween('created_at', [$start, $end])
               ->get();
Run Code Online (Sandbox Code Playgroud)

或者

$posts = Mjblog::where('created_at', '>=', $start)
               ->where('created_at', '<=', $end)
               ->get();
Run Code Online (Sandbox Code Playgroud)

另一篇有用的文章强调了不可SARGable 谓词和反模式的缺点


seb*_*ign 7

如果您想从单个实例中获取年份和月份,Mjblog您可以像这样访问它们:

$year = $post->created_at->year;
$month = $post->created_at->month;
Run Code Online (Sandbox Code Playgroud)

阅读有关Carbon\Carbon getter 文档的更多信息。