【问题标题】:How to select year and month from the created_at attributes of database table in laravel 5.1?laravel 5.1 如何从数据库表的 created_at 属性中选择年份和月份?
【发布时间】:2015-12-26 17:46:08
【问题描述】:

我的问题是我想从 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();

【问题讨论】:

  • 你的意思是你的返回结果应该包含给定Mjblog模型的所有年份和月份,如果是,那你为什么要这样做:$post->where('created_at',$post)->get();?跨度>
  • 请稍微澄清一下您的问题。
  • 我的确切需要是当我点击存档月份和年份时需要显示有created_at日期字段的数据库表的内容。

标签: php sql laravel eloquent laravel-5.1


【解决方案1】:

绩效考核

虽然接受的答案可能会解决 OP 问题,但这 不是 OPTIMAL SOLUTION数据库性能。 因为当whereYear()whereMonth() 帮助器应用于查询记录时,它会进行查询Non-SARGable。这意味着如果比较列 created_at 在数据库中被索引,则在搜索数据时会忽略此索引。见What makes a SQL statement sargable?

考虑以下表达式

$posts = Mjblog::whereYear('created_at', '=', $year)
               ->whereMonth('created_at', '=', $month)
               ->get();

查询结果会是这样的

select * 
from mjblog 
where year(`created_at`) = :year 
  and month(`created_at`) = :month

可以清楚地看到上述查询是不可分割的,因为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

现在SARGable表达式可以写成


select * 
from mjblog 
where created_at between :start and :end

或者

select * 
from mjblog 
where created_at >= :start 
  and created_at <= :end

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


$posts = Mjblog::whereBetween('created_at', [$start, $end])
               ->get();

或者

$posts = Mjblog::where('created_at', '>=', $start)
               ->where('created_at', '<=', $end)
               ->get();

另一篇有用的文章强调了Non-SARGable Predicates & Anti-Patterns 的缺点

【讨论】:

  • 简单问题:您是否建议该解决方案比公认的解决方案更快(在查询时间)?
  • @ToniTegarSahidi 是,如果 created_at 是索引列,这种方法将利用添加的索引,而另一种方法将忽略,因为 year() 和 month() 函数将应用于查询,这将产生一个新值除了索引值
【解决方案2】:

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

$year = $post->created_at->year;
$month = $post->created_at->month;

阅读更多关于Carbon\Carbongetters documentation的信息。

【讨论】:

    【解决方案3】:

    查询生成器中有可用的日期助手:

    $post = Mjblog::whereYear('created_at', '=', $year)
                  ->whereMonth('created_at', '=', $month)
                  ->get();
    

    【讨论】:

    • 您也可以使用-&gt;whereMonth('created_at', $month)。两者都可以。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-14
    • 2011-03-21
    • 1970-01-01
    • 2018-01-23
    • 2017-10-13
    相关资源
    最近更新 更多