【问题标题】:CakePHP Multi-Conditional SQL statementCakePHP 多条件 SQL 语句
【发布时间】:2017-09-06 17:14:41
【问题描述】:

使用 CakePHP 3.4.12 版和 MySQL... 我在使用 SQL 时遇到了问题,然后将 SQL 导入 CakePHP。我想查看可能今天进入和退出的记录,今天或之前进入并且可能在今天或之后退出,或者他们在今天或之前进入但仍然没有退出时间。并跳过任何标记为非活动 (inactive=true) 的记录。

数据摘录:

id  name    time_in             time_out            inactive
174 smith   8/15/2017 21:00     8/15/2017 21:22     NULL
175 roberts 8/15/2017 21:21     8/15/2017 21:21     NULL
176 Wagner  9/2/2017 4:40       9/3/2017 18:29      0
177 JAmes   9/1/2017 3:35       NULL                0
178 john    9/4/2017 3:59       9/4/2017 22:22      NULL
180 erwer   9/4/2017 4:01       NULL                1
181 waynbe  9/4/2017 4:02       NULL                NULL
182 Roger   9/4/2017 22:21      9/4/2017 22:22      NULL
183 Felix   9/4/2017 22:24      NULL                NULL

如果我在 SQL 中出错了,我想查找所有记录

NOT 'inactive'(不是 TRUE)

还有哪里

'time_in' time_out' >= '2017-09-04 00:00:00'

---- 或 ----

'time_out' 为 NULL AND 'time_in'

想要的返回结果是:

id  name    time_in             time_out            inactive
177 JAmes   9/1/2017 3:35       NULL                0
178 john    9/4/2017 3:59       9/4/2017 22:22      NULL
181 waynbe  9/4/2017 4:02       NULL                NULL
182 Roger   9/4/2017 22:21      9/4/2017 22:22      NULL
183 Felix   9/4/2017 22:24      NULL                NULL

我试图实现的条件 SQL 是:

WHERE (time_in <= '2017-09-04 23:59:59' AND time_out >= '2017-09-04 00:00:00') 
OR (isnull(time_out) AND time_in <= '2017-09-04 23:59:59') 
AND inactive != 1 

这给出了结果并且缺少数据:

id  name    time_in             time_out            inactive
177 JAmes   9/1/2017 3:35       NULL                0
178 john    9/4/2017 3:59       9/4/2017 22:22      NULL
182 Roger   9/4/2017 22:21      9/4/2017 22:22      NULL

但是,在 CakePHP 中尝试使用:

$query= $this->StationEntries->find('all')
            ->andWhere(['time_in <='=> $dateIn, 'time_out >='=>$dateOut])
            ->orWhere(['isnull(time_out)', 'time_in <='=> $dateIn])
            ->andWhere(['inactive !='=>true]);

创建 SQL:

WHERE 
(
 (
  (
    time_in <= '2017-09-04 23:59:59' 
    AND time_out >= '2017-09-04 00:00:00'
  ) 
  OR (
    isnull(time_out) 
    AND time_in <= '2017-09-04 23:59:59'
  )
 ) 
 AND inactive != 1
) 

这将返回以下结果,并且缺少更多记录。

id  name    time_in             time_out            inactive
177 JAmes   9/1/2017 3:35       NULL                0

除了没有过滤掉inactive记录之外,以下操作可以正常工作。

$query= $this->StationEntries->find('all')
        ->where(['time_in <='=> $dateIn, 'time_out >='=>$dateOut])
        ->orWhere(['isnull(time_out)', 'time_in <='=> $dateIn]);

我在书中看过:

从 3.5.0 开始,不推荐使用 orWhere() 方法。 这种方法创建了难以预测的 SQL,基于 当前查询状态。使用 where() 代替,因为它更可预测 并且更容易理解行为。1

所以我在两个方面寻求帮助:

  1. 我在 SQL WHERE 子句中的错误在哪里?应该是什么?
  2. 如何将其转换为 CakePHP Query builder 以及如何在避免 orWhere() 方法的同时做到这一点?

感谢您的帮助。

【问题讨论】:

    标签: php mysql cakephp


    【解决方案1】:

    Per docs, to add an 'OR' clause, you need to have the 'OR' be the key in the array。我认为您正在寻找:

    ->where(
       [
          'time_in <=' => $dateIn, 'time_out >=' => $dateOut,
          'OR' => [
             ['time_out IS NULL', 'time_in <=' => $dateIn
          ]
       ]
    )->andWhere( [ 'inactive !=' => 1 ] )
    

    基本上,这应该会导致:

    (
       (time_in < dateIn AND time_out < dateOut)
       OR ( time_out IS NULL AND time_in < dateIn)
    ) 
    AND ( inactive != 1 )
    

    你可以简化为:

    ->where( [ 'time_in <=' => $dateIn ], [ 'inactive !=' => 1 ] )
    ->andWhere(
    [
       'time_out >=' => $dateOut,
       'OR' => [ 'time_out IS NULL' ]
    ])
    

    【讨论】:

    • @ cwallenpoole :之前尝试过 OR=> 但尝试了简化版本,CakePHP 创建了 sql: WHERE ( time_in = '2017 -09-04 00:00:00' AND time_out IS NULL ) 虽然 OR 被编码,但在实际 SQL 中没有。上述解决方案均未返回结果。
    【解决方案2】:

    首先,IS NULL 不等于 !TRUE ( != 1 )。那是第一个问题。固定。

    正确的 SQL 来自(感谢@cwallenpoole 朝着正确的方向推动)原始查询的简化:

    ->where( [ 'time_in <=' => $dateIn,  'inactive IS NULL',
    'OR' =>(['time_out >=' => $dateOut,'time_out IS NULL' ])])
    

    如果你从你的架构中删除空值,那么它看起来像:

    ->where( [ 'time_in <=' => $dateIn,  'inactive !=' =>1,
    'OR' =>(['time_out >=' => $dateOut,'time_out IS NULL' ])])
    

    这导致 CakePHP 查询:

    WHERE 
      (
        time_in <= '2017-09-04 23:59:59' 
        AND inactive IS NULL 
        AND (
          time_out >= '2017-09-04 00:00:00' 
          OR time_out IS NULL
        )
      ) 
    

    这会返回正确的行。

    【讨论】:

    • 另外,因为 NULL 字段将与 IS NOT TRUE and IS NOT FALSE 一起返回,所以我重新设计了表格以从将被测试为状态 (TRUE/FALSE) 的字段中删除 NULL 值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-21
    • 1970-01-01
    • 2011-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-28
    相关资源
    最近更新 更多