如何在 Laravel 7 中使用原始 SQL 查询创建范围?
Posted
技术标签:
【中文标题】如何在 Laravel 7 中使用原始 SQL 查询创建范围?【英文标题】:How to make a scope with a raw SQL query in Laravel 7? 【发布时间】:2021-07-09 22:15:41 【问题描述】:问题
我正在尝试使用此 SQL 查询 在我的 模型 中创建一个 范围:
SELECT *
FROM ro_container_events
WHERE (container_id, location_timestamp, id)
IN (
SELECT distinct container_id, MAX(location_timestamp) AS lts, MAX(id) AS rce_id
FROM ro_container_events
GROUP BY container_id
)
模型名称是 ContainerEvent,我的数据库中的表名称是 ro_container_events。
另外,我知道 SQL 查询是有效的,因为我在我的 mysql 管理工具 (HeidiSQL) 中运行了它,它返回了正确的行。
我尝试过的
我的范围(在我的 ContainerEvent 模型中)当前如下所示:
public function scopeLatestEventForContainers($query)
return $query->select(DB::raw('
SELECT *
FROM ro_container_events
WHERE (container_id, location_timestamp, id)
IN (
SELECT distinct container_id, MAX(location_timestamp) AS lts, MAX(id) AS rce_id
FROM ro_container_events
GROUP BY container_id
)'
)
);
但它不返回任何行?
我的研究
我一直在搜索这个主题,但似乎找不到我的范围有什么问题......
Laravel 文档说我们可以使用:
DB::raw('...')
为了进行特定的 SQL 查询。
而且我在其他一些线程上看到我应该能够使用以下内容创建范围:
return $query->select(DB::raw('...');
【问题讨论】:
你试过 print_r() 你把 print_r 里面的函数返回什么? 【参考方案1】:我只是使用 Laravel 查询构建器尝试您的 SQL 语法,使用方法 toSql()
的结果返回您需要的确切内容。
SELECT * FROM ro_container_events WHERE (container_id, location_timestamp, id) IN (
SELECT distinct container_id, MAX(location_timestamp) AS lts, MAX(id) AS rce_id
FROM ro_container_events
GROUP BY container_id
)
试试这个功能:
public function scopeLatestEventForContainers($query)
return $query->whereIn(\DB::raw('(container_id, location_timestamp, id)'), function ($q)
$q->distinct()->select(\DB::raw('
container_id,
MAX(location_timestamp) AS lts,
MAX(id) AS rce_id FROM `ro_container_events`
'))->groupBy('container_id');
);
希望对你有帮助:)
最好, vreedom18
【讨论】:
【参考方案2】:试试 Eloquent:
//as your where in select this must return just one row with 3 field
$in = ContainerEvent::distinct('container_id', 'location_timestamp', 'id')->where(fn($q) =>
'id' => ContainerEvent::max('id')
'location_timestamp' => ContainerEvent::max('location_timestamp')
])->get();
但这可能是错误的,因为 db 结构中存在野心。
【讨论】:
你能给我ContainerEvent的结果吗::get(container_id, max(location_timestamp), max(id)) ->distinct(); ? 它没有给出任何结果。如果我错了,请纠正我,但你不能给 get() 提供 3 个参数...? 试试我的项目这种情况。这不是最好的,但肯定会做你需要的。答案已更新。以上是关于如何在 Laravel 7 中使用原始 SQL 查询创建范围?的主要内容,如果未能解决你的问题,请参考以下文章
如何在原始 sql WHERE IN [LUMEN/LARAVEL] 中绑定命名参数
Laravel 查询构建器 - 如何按别名分组,或进行原始 groupBy