我在这里看过大多数其他解决方案,但它们似乎都不适合我。我有一张大约有100K行的表。
每一行都是来自iot设备的记录,其中包含该设备的唯一ID。设备ID可能有100K的10K行。
Reading::whereIn('device_id', $ids)->orderBy('created_at',
'DESC')->groupBy('device_id')->get()->
我能够将我需要的ID拉出来并通过“device_id”将它们组合在一起作为上面的查询,但是它选择了第一个结果,而不是每个id的最后一个结果。
如何获取每个ID而不是最旧的最新记录?
我查看了laravel集合和reverse(),first(),latest();选项,但我仍然无法得到它
有什么想法吗?
更新
我能想出的最好的是下面的查询,它会获取每个device_id的最新记录
SELECT t1.* FROM readings t1 WHERE t1.id = (SELECT t2.id FROM readings
t2 WHERE t2.device_id = t1.device_id ORDER BY t2.id DESC LIMIT 1)
然后我将遍历这些结果,只获取用户有权访问的记录。
不漂亮,但它现在有效。
如果有人确实找到了雄辩的话,请回答
答案 0 :(得分:0)
我相信这应该有用吗?
Reading::select('device_id', 'id', DB::raw('MAX(created_at) AS latest'))->whereIn('device_id', $ids)->orderBy('latest', 'DESC')->groupBy('device_id')->get();
希望这有帮助!
答案 1 :(得分:0)
好的,我相信这可行,因为以前的尝试并没有:
ws:\\localhost\
您基本上运行了一个'子查询'。因此,首先按照您需要的顺序检索结果,然后运行第二个查询对它们进行分组。
答案 2 :(得分:0)
这是一个值得思考的棘手问题。一旦你在数据库术语中重新构建了问题,就像在"获取MySQL查询中每个id的最大记录一样,很容易找到很多SO答案。
这是SO上的一个评价很高的例子:Retrieving the last record in each group
在您更新的查询中,子查询实际上是为我认为的每一行重新计算的。我们可以通过将读数加入自身来做得更好(查看以上链接作为参考)
SELECT r1.*
FROM readings r1
LEFT JOIN readings r2
ON r2.device_id = r1.device_id
AND r1.date_created < r2.date_created
WHERE r2.device_id IS NULL # there is no row with a date_created greater than r1's
;
device_id和date_created上的索引是提高速度的第一步
答案 3 :(得分:0)
我终于能够把它整理好了。以下查询在laravel中返回我想要的内容。
$sql = Reading::select('created_at', 'column1', 'column2', 'column3', 'column4', 'column5',
'column6')->whereIn('device_id', ['0','0'])->toSql();
// 0 is just "empty" value, it doesn't matter here yet
$db = DB::connection()->getPdo();
$query = $db->prepare($sql);
// real ids im looking for
$query->execute(array('ffvr5g6h', 'ccvl5f4rty'));
$collection = collect($query);
// change this to take ever (n) record
//$collection = $collection->every(100);
$collection = $collection->groupBy('device_id');
foreach ($collection as $collect) {
// process data
$end = $collect->last();
print_r($end);
}
上面的查询在大约半秒内查询100K行,然后将其转换为laravel的集合,一次在集合i中按id分组,然后从该结果中获取最后一条记录。
感谢所有试图提供帮助的人:)