PostgreSQL: найти строки в одной таблице на основе максимального количества связанных записей в других таблицах. - PullRequest
0 голосов
/ 19 июня 2020

У меня есть следующие таблицы

vehicles - id, name

vehicle_settings - id, settings, vehicle_id, company_id, updated_at, updated_by

vehicle_licenses - id, license_number, vehicle_id, company_id, updated_at, updated_by

users - id, name, email

Одно транспортное средство может иметь несколько записей в vehicle_settings и несколько записей в vehicle_licenses. Возможно, у транспортного средства нет Vehicle_settings или лицензий на автомобиль.

Теперь мне нужен список всех транспортных средств с пользователем, у которого есть последнее обновление настроек автомобиля или лицензии. Я также должен иметь возможность фильтровать список с идентификатором транспортного средства и иметь возможность подсчитывать все транспортные средства, которые соответствуют отфильтрованному условию.

Итак, я попробовал следующий запрос

SELECT DISTINCT ON (v.id) v.id,
(
SELECT
    JSON_BUILD_OBJECT(
      'id', u.id, 
      'name', u.name,
      'email', u.email
    )
FROM users u WHERE u.id=updates.updated_by  AND updates.updated_at = MAX(updates.updated_at) 
) AS updated_by,
MAX(updates.updated_at) AS updated_at,
COUNT(*) over () 
FROM vehicles v 
LEFT JOIN  LATERAL(
select foo.updated_by,foo.updated_at FROM (
select vs.updated_by,vs.updated_at from vehicle_settings vs WHERE vs.vehicle_id = v.id 
 UNION         
select vl.updated_by,vl.updated_at from vehicle_licenses vl WHERE vl.vehicle_id = v.id
) AS foo order by updated_at desc  LIMIT 1    
) AS updates ON TRUE
WHERE v.id 'c4ced8df-c93f-45e8-806f-f7d5f20d9d75'
GROUP BY v.id, updates.updated_by,updates.updated_at ;

Это query работает достаточно хорошо, однако подсчет вводит в заблуждение. Количество получаемых мной счетчиков больше, чем количество транспортных средств. Возможно, он принимает записи из LEFT LATERAL JOIN, я думаю.

1 Ответ

1 голос
/ 19 июня 2020
SELECT v.*, u.*,
       COUNT(*) FILTER (WHERE v.id = 'c4ced8df-c93f-45e8-806f-f7d5f20d9d75') OVER ()
FROM vehicles AS v
   LEFT JOIN (SELECT DISTINCT ON (vehicle_id)
                vehicle_id, updated_by
         FROM (SELECT vehicle_id, updated_by, updated_at
               FROM vehicle_settings
               UNION ALL
               SELECT vehicle_id, updated_by, updated_at
               FROM vehicle_licenses) AS x
         ORDER BY vehicle_id, updated_at DESC) AS vu
      ON v.id = vu.vehicle_id
   LEFT JOIN users AS u
      ON vu.updated_by = u.id;
...