我面临着必须重构我的模型的问题,以便每个模型能够基于一个刻度存在多个实例。可以有很多刻度,它们从零开始递增,一个接着一个,每个刻度标识一个时间段。我想根据可用的最高刻度获取表上的许多行。因此,搜索第
component
列将返回第 tick
列的最高记录。此外,蜱虫可能尚未发生,因此需要以如下方式检查蜱虫:
$components = $this->where('tick', '<=', $tick)->orderBy('tick', 'DESC')->get();
因此,这可以通过数字选择
tick
之前发生的 all
记录来删除所有未来出现的 $tick
。
考虑这个数据集。
+----+------+------------+--------+
| id | tick | branch | amount |
+----+------+------------+--------+
| 1 | 2 | components | 100 |
| 2 | 2 | research | 50 |
| 3 | 3 | research | 55 |
| 4 | 4 | research | 60 |
+----+------+------------+--------+
假设
$tick
为 3,这意味着从 id
1
、2
和 3
中选择了 3 条记录。但我想要的是 id
1
和 3
的记录,因为 2
已过时,因为它发生在 3
之前。
换句话说,我期望达到低于某个值的最高跳动记录。为了验证该场景,请参阅下文。
+----+------+------------+--------+--------+
| id | tick | branch | type | amount |
+----+------+------------+--------+--------+
| 1 | 2 | components | light | 100 |
| 2 | 2 | components | medium | 90 |
| 3 | 2 | components | heavy | 80 |
| 4 | 3 | components | light | 110 |
| 5 | 4 | components | light | 120 |
| 6 | 2 | research | waves | 50 |
| 7 | 3 | research | waves | 55 |
| 8 | 4 | research | waves | 60 |
+----+------+------------+--------+--------+
有了这个,当
$tick
是 4
时,你会期望:
忽略行
1
,因为它具有tick
和3
的未来
4
选择行
2
和 3
作为其唯一的 medium
/ heavy
为 components
选择行
5
和 8
忽略行 4
、6
和 7
所以发生的事情是选择每个分支和类型的最后一个刻度。我想以下内容就足够了。
$components = $this->where([['branch' => 'components'], ['type' => 'light'], ['tick', '<=', $tick]])->orderBy('tick', 'DESC')->first();
但这似乎相当麻烦,考虑到
branch
和 type
可能有许多不同的版本。有没有办法要求为匹配 tick
和 branch
的所有列选择 type
的最后一次出现(或最大值)?
我尝试了各种组合并阅读了在线文档,但似乎找不到适合我需求的组合。我想象
with
具有某种闭包函数。谁能建议最干净/最好的方法?
在这种情况下,我们可以将表本身连接起来,同时在给定的
$tick
和 branch
分组中过滤最大 type
,然后返回该集合中的所有不同结果:
ProductTick::from('product_ticks as t1')
->join('product_ticks as t2', function ($join) {
$join->on('t1.branch', '=', 't2.branch')
->on('t1.type', '=', 't2.type')
->on('t1.tick', '=', DB::raw('(SELECT MAX(tick) FROM product_ticks WHERE branch = t2.branch AND type = t2.type)'));
})
->select('t1.*')
->distinct('id')
->get();