CakePHP多条件SQL语句

时间:2017-09-06 17:14:41

标签: php mysql cakephp

使用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' 不活跃' (不是真的)

也在哪里

  

'的 time_in ' < =' 2017-09-04 23:59:59'和' time_out ' > =   ' 2017-09-04 00:00:00'

     

----或----

     

'的 TIME_OUT '是NULL并且' time_in ' < =' 2017-09-04 23:59:59'

所需的返回结果是:

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

以下操作正常,但不会过滤掉非活动记录。

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

我在书中读过:

  

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

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

  1. 我在SQL WHERE子句中的错误在哪里?它应该是什么?
  2. 如何将其转换为CakePHP查询构建器以及如何在避免使用 orWhere()方法的情况下执行此操作?
  3. 感谢您的帮助。

2 个答案:

答案 0 :(得分: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' ]
])

答案 1 :(得分:0)

首先,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
    )
  ) 

这会返回正确的行。