У меня есть 2 таблицы: drivers
и drivers_locations
.
Я хочу создать вычисляемое поле в таблице drivers
, которое возвращает последнее вставленное местоположение драйвера.
В таблице drivers_locations
есть следующие столбцы:
- id: uuid
- driver_id: uuid
- location: geography
- timestamp: bigint
timestamp
в миллисекундах с эпохи Unix. (например, 1673129623999).
Вот моя нубская неудачная попытка добиться этого:
CREATE OR REPLACE FUNCTION public.fn_driver_last_location(driver_row drivers)
RETURNS geometry
LANGUAGE sql
IMMUTABLE
AS $function$
SELECT loc.location
FROM driver_locations loc
inner join drivers drv
on loc.driver_id = drv.id
group by loc.location_recorded_time_unix, loc.location, drv.id
HAVING loc.location_recorded_time_unix = MAX(loc.location_recorded_time_unix) and drv.id = driver_row.id;
$function$
;;
Есть идеи?
это дает мне эту ошибку: column "loc.location" must appear in the GROUP BY clause or be used in an aggregate function
Не связано, но: использование эпохи unix вместо правильного столбца timestamp
считается плохим дизайном. См., например. здесь
Вы можете отсортировать местоположения по времени и ограничить результат одной строкой. Вам также не нужно соединение.
CREATE OR REPLACE FUNCTION public.fn_driver_last_location(driver_row drivers)
RETURNS geometry
LANGUAGE sql
STABLE
AS $function$
SELECT loc.location
FROM driver_locations loc
where loc.driver_id = driver_row.id
order by loc.location_recorded_time_unix desc
limit 1;
$function$
;
Функция, которая выбирает из таблиц базы данных, никогда не должна быть объявлена как immutable
, поскольку она может возвращать разные результаты, даже если вызывается с одним и тем же параметром.
попробуйте это:
SELECT loc.location FROM driver_locations loc INNER JOIN drivers drv ON loc.driver_id = drv.id WHERE drv.id = driver_row.id GROUP BY drv.id HAVING loc.location_recorded_time_unix = MAX(loc.location_recorded_time_unix)