我会把它留在这里以防有人需要它。这是对 Laravel 的 @Kickstart 解释。
$sub = DB::query()->selectRaw(implode(', ', [
'Loc1.latitude as latitude_from',
'Loc1.longitude as longitude_from',
'Loc2.latitude as latitude_to',
'Loc2.longitude as longitude_to',
'ST_Distance_Sphere(point(Loc1.longitude, Loc1.latitude),point(Loc2.longitude, Loc2.latitude)) as dist',
]))->fromSub(function ($query) {
$query->selectRaw(implode(', ', [
'latitude',
'longitude',
'@Cnt1 := @Cnt1+1 AS SeqCnt',
]))->fromSub(function ($query) {
$query->select([
'latitude',
'longitude',
])->from('tracker_coords')
->where('tracker_id', 155)
->whereBetween('created_at', [
'2020-10-02T13:00:00.000000Z',
'2020-10-03T07:45:00.000000Z'
])
->orderBY('created_at');
}, 'Sub0')->crossJoin(
DB::raw('(SELECT @Cnt1:=0) as Sub1')
);
}, 'Loc1')->joinSub(function($query) {
$query->selectRaw(implode(', ', [
'latitude',
'longitude',
'@Cnt2 := @Cnt2+1 AS SeqCnt',
]))->fromSub(function ($query) {
$query->select([
'latitude',
'longitude',
])->from('tracker_coords')
->where('tracker_id', 155)
->whereBetween('created_at', [
'2020-10-02T13:00:00.000000Z',
'2020-10-03T07:45:00.000000Z'
])
->orderBY('created_at');
}, 'Sub0')->crossJoin(
DB::raw('(SELECT @Cnt2:=1) Sub1')
);
}, 'Loc2', 'Loc1.SeqCnt', '=', 'Loc2.SeqCnt')->get();
简单用法:
$coords = $this->getConcatQueryString([
't1.latitude as latitude_from',
't1.longitude as longitude_from',
't2.latitude as latitude_to',
't2.longitude as longitude_to',
'ST_Distance_Sphere(point(t1.longitude,t1.latitude),point(t2.longitude, t2.latitude)) as dist',
], fn($query) => $query
->from('tracker_coords')
->select([
'latitude',
'longitude',
'created_at',
])
->where('tracker_id', $tracker->id)
->whereBetween('created_at', [
$item->event_at,
$item->event_to,
])
->orderBy('created_at')
)->get()->sum('dist');
private function getConcatQuery(array $select, $f)
{
return DB::query()->selectRaw(implode(', ', $select))
->fromSub(function ($query) use ($f) {
$query->selectRaw(implode(', ', [
'*',
'@Cnt1 := @Cnt1+1 AS SeqCnt',
]))->fromSub($f, 'Sub0')->crossJoin(
DB::raw('(SELECT @Cnt1:=0) as Sub1')
);
}, 't1')->joinSub(function($query) use ($f) {
$query->selectRaw(implode(', ', [
'*',
'@Cnt2 := @Cnt2+1 AS SeqCnt',
]))->fromSub($f, 'Sub0')->crossJoin(
DB::raw('(SELECT @Cnt2:=1) Sub1')
);
}, 't2', 't1.SeqCnt', '=', 't2.SeqCnt');
}