之前工作遇到一个情境需要捞出取消订单状态为 0,1 或没有取消单的订单,然後要再加上其他条件,像是订单状态、时间和供应商名称。
SQL 大概是长这样,OR的条件用括号刮起来
SELECT * FROM orders
WHERE status = 1
AND (/* 括号 */
EXISTS (
/* 取消订单状态为 0 或 1 */
SELECT * FROM cancellations
WHERE orders.id = cancellations.order_id
AND cancellations.status in (0, 1)
) OR NOT EXISTS (
/* 或没有取消订单 */
SELECT * FROM cancellations
WHERE orders.id = cancellations.order_id
)
)/* 括号 */
AND DATE (created_at) >= "2021-07-01 00:00:00"
AND DATE (created_at) <= "2021-07-31 23:59:59"
AND supplier = "appple";
所以写成 Laravel query 长这样
Order::where('status', 1)
whereHas('cancellation', function($query) {
return $query->whereIn('status', [0, 1]);
})
->orWhereDoesntHave('cancellation')
->where('created_at', '>=', '2021-07-01 00:00:00')
->where('created_at', '<=', '2021-07-31 23:59:59')
->where('supplier', 'apple');
问题来了!我要怎麽加那个「括号」呢!?
爬了很多文和尝试,得出的结论是,以这个 case ,最简单的方式就是不加!只是把 or 条件移到最後,像这样。结果会是我要的。
Order::where('status', 1)
->where('created_at', '>=', '2021-07-01 00:00:00')
->where('created_at', '<=', '2021-07-31 23:59:59')
->where('supplier', 'apple')
/* 下面这段放最後面 */
whereHas('cancellation', function($query) {
return $query->whereIn('status', [0, 1]);
})
->orWhereDoesntHave('cancellation');
但这样的缺点是可能比较难维护,例如之後的人要再加一个条件,他不知道这个情形,就直接在最後面接上一个新条件就 GG 了!而且如果 OR 的条件不只一个,这个写法也不行。
後来我查了 Laravel query Exists
和 Not Exists
的写法,拼出了以下的写法,结果也是对的!只是比较丑...
逻辑基本上就是想办法把 SQL 用 Laravel query 的语法硬写出来。
Order::where('status', 1)
whereExists(function($query) {
return $query->from('cancellations')
->whereColumn('orders.id', 'cancellations.order_id')
->whereIn('cancellations.status', [0, 1])
->orWhereNotExists(function ($query){
return $query->from('cancellations')
->whereColumn('orders.id', 'cancellations.order_id');
});
})
->where('created_at', '>=', '2021-07-01 00:00:00')
->where('created_at', '<=', '2021-07-31 23:59:59')
->where('supplier', 'apple');
成功是成功了,但我还是不是很满意,觉得这样的写法很不优雅。後来跟同事讨论才知道原来可以把 where
当括号来用!知道 Laravel query 的括号怎麽写後就单纯很多了!
Order::where('status', 1)
->where(function ($query) {/* 括号! */
return $query->whereHas('cancellation', function($query) {
return $query->whereIn('status', [0, 1]);
})->orWhereDoesntHave('cancellation');
})/* 括号! */
->where('created_at', '>=', '2021-07-01 00:00:00')
->where('created_at', '<=', '2021-07-31 23:59:59')
->where('supplier', 'apple');
所以就算之後里面还要多个括号就再加 where
就好~满足~
如果条件是变数,可以用 use
把变数传进 where
$status = [0, 1]; /* 状态变数 */
Order::where('status', 1)
->where(function ($query) use ($status) {/* 传 $status 进去 */
return $query->whereHas('cancellation', function($query) {
return $query->whereIn('status', $status);/* 用在这 */
})->orWhereDoesntHave('cancellation');
})
->where('created_at', '>=', '2021-07-01 00:00:00')
->where('created_at', '<=', '2021-07-31 23:59:59')
->where('supplier', 'apple');
总算要进入MVC架构介绍了... 前面整整15天都在讲基础的部分,简易说明资料库如何连线、C# 基本...
当遇到大量且有规律的资料就可以用ListView清单显示,例如:商品讯息,联络人... ListVi...
DBABootcamp 如果你正在思考未来的职涯规划,准备投入或转换 DBA (资料库管理师) 跑道...
一、整理变数重声明与重名变数的描述。 变数重声明,对已经声明过的变数,再次声明。 前提条件如下: 变...
1. 原子操作是什麽? 原子操作,操作进行的过程不能被中断。也就是说,某个值在原子操作的过程中,CP...