【问题标题】:Timestamp comparison on where clause randomly working?where 子句中的时间戳比较随机工作?
【发布时间】:2021-02-09 22:19:48
【问题描述】:

我有一个旧数据库,其中 FastStart_startFastStart_End 列是 varchars。

使用 Laravel 查询构建器,以下查询

$referrals = \DB::table('users')->join('order_details', 'order_details.user_id', 'users.id')
            ->join('users as sponsor', 'sponsor.id', '=', 'users.sponsor_id')
            //->where('order_details.created_at', '>=', 'sponsor.FastStart_Start')
            ->where('order_details.created_at', '<=', 'sponsor.FastStart_End')
            ->select('users.username', 'users.email',  'order_details.created_at', 'users.sponsor_id',
                 'sponsor.FastStart_Start', 'sponsor.FastStart_End')
            ->get();

给出这个结果:

 #items: array:3 [
    0 => {#2792
      +"username": "annalise92"
      +"email": "luisa.grimes@example.net"
      +"created_at": "2020-06-15 21:32:23"
      +"sponsor_id": 2085929
      +"FastStart_Start": "2020-06-01 00:00:00"
      +"FastStart_End": "2020-06-30 00:00:00"
    }
    1 => {#2832
      +"username": "nbarton"
      +"email": "gibson.ibrahim@example.com"
      +"created_at": "2020-06-15 21:32:23"
      +"sponsor_id": 2085929
      +"FastStart_Start": "2020-06-01 00:00:00"
      +"FastStart_End": "2020-06-30 00:00:00"
    }
    2 => {#2836
      +"username": "maxine56"
      +"email": "cwuckert@example.net"
      +"created_at": "2020-06-15 21:32:23"
      +"sponsor_id": 2085929
      +"FastStart_Start": "2020-06-01 00:00:00"
      +"FastStart_End": "2020-06-30 00:00:00"
    }
  ]

从结果可以清楚地看出FastStart_Start 小于order_details.created_at

但是,如果我取消注释该行

//->where('order_details.created_at', '>=', 'sponsor.FastStart_Start')

从查询生成器中,结果集将为空。

这怎么可能?这是否与 FastStart_Start 是一个 varchar 列有关?如果是这样,为什么不影响与FastStart_End的比较?

使用toSql 命令我看到查询生成器正在创建这个查询:

select users.username
     , users.email
     , order_details.created_at
     , users.sponsor_id
     , sponsor.FastStart_Start
     , sponsor.FastStart_End 
  from users 
  join order_details 
    on order_details.user_id = users.id 
  join users sponsor 
    on sponsor.id = users.sponsor_id 
 where order_details.created_at >= ? 
   and order_details.created_at <= ?

如果我取消注释 where 行,知道为什么结果集是空的吗?

编辑:另一个查询的 tosql 结果是:

select users.username
     , users.email
     , order_details.created_at
     , users.sponsor_id
     , sponsor.FastStart_Start
     , sponsor.FastStart_End 
  from users 
  join order_details 
    on order_details.user_id = users.id 
  join users sponsor 
    on sponsor.id = users.sponsor_id 
 where order_details.created_at <= ?

【问题讨论】:

  • 修复数据库怎么样?
  • @Strawberry 是完全相同的查询,只是最后没有order_details.created_at &gt;= ? and
  • 可以通过DB::enableQueryLog()开启查询日志,然后使用DB::getQueryLog()输出查询;它应该显示查询和正在使用的参数。
  • @TimLewis 啊,很高兴知道!我刚试过,我得到一个包含 3 个值的数组,第一个是 toSql() 结果,第二个是 getBindings(),第三个是 time
  • @MarcinOrlowski 实际上我现在在本地修复了数据库,但问题仍然存在。

标签: mysql laravel laravel-5


【解决方案1】:

这与最终的 SQL 语句将sponsor.FastStart_Start 视为文字字符串有关。

您的查询工作的原因是从字符串比较的角度来看:

'2020-06-15 21:32:23' &gt;= 'sponsor.FastStart_Start'

还有

'2020-06-15 21:32:23' &gt;= 'anystring' 也是 FALSE

还有

'2020-06-15 21:32:23' &lt;= 'sponsor.FastStart_Start'正确

还有

'2020-06-15 21:32:23' &lt;= 'anystring' 也是 TRUE

解决方案 1(首选)

使用-&gt;whereColumn() 方法进行比较,这样你就告诉 Laravel 你不想把你的 当作 字符串字面量This is documented here

$referrals = \DB::table('users')->join('order_details', 'order_details.user_id', 'users.id')
            ->join('users as sponsor', 'sponsor.id', '=', 'users.sponsor_id')
            ->whereColumn('order_details.created_at', '>=', 'sponsor.FastStart_Start')
            ->whereColumn('order_details.created_at', '<='. 'sponsor.FastStart_End')
            ->select('users.username', 'users.email',  'order_details.created_at', 'users.sponsor_id',
                 'sponsor.FastStart_Start', 'sponsor.FastStart_End')
            ->get();

解决方案 2(替代方案)

-&gt;whereRaw() 方法中使用 RAW 子句:

$referrals = \DB::table('users')->join('order_details', 'order_details.user_id', 'users.id')
            ->join('users as sponsor', 'sponsor.id', '=', 'users.sponsor_id')
            ->whereRaw('order_details.created_at >= sponsor.FastStart_Start')
            ->whereRaw('order_details.created_at <= sponsor.FastStart_End')
            ->select('users.username', 'users.email',  'order_details.created_at', 'users.sponsor_id',
                 'sponsor.FastStart_Start', 'sponsor.FastStart_End')
            ->get();

这两种解决方案应该会导致相同的结果,而查询构建级别的处理方式略有不同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-05
    • 2015-06-26
    相关资源
    最近更新 更多