Перекрестное соединение PostgreSQL с использованием max возвращает null

#sql #postgresql #max #cross-join

#sql #postgresql #max #перекрестное соединение

Вопрос:

Я хочу выбрать значение max() столбца modified_at в каждой из нескольких таблиц:

 select 
max(a.modified_at) as a_modified_at,
max(b.modified_at) as b_modified_at,  
max(c.modified_at) as c_modified_at 
from a, b, c;
  

Это работает правильно, если в каждой из таблиц есть хотя бы 1 строка.
Проблема в том, что когда только одна из таблиц содержит 0 строк, для всех таблиц возвращается значение null:

 null,null,null
  

Какое решение возвращает правильные значения для таблиц, в которых есть строки?
PostgreSQL-10

Ответ №1:

Использование OUTER JOIN s должно сделать это

 select 
max(a.modified_at) as a_modified_at,
max(b.modified_at) as b_modified_at,  
max(c.modified_at) as c_modified_at 
from a outer join b outer join c;
  

но, возможно, более простым вариантом было бы использовать вместо этого 3 подзапроса:

 select 
(select max(modified_at) from a) as a_modified_at,
(select max(modified_at) from b) as b_modified_at,  
(select max(modified_at) from c) as c_modified_at;
  

Комментарии:

1. Мне больше нравится решение с подзапросами. Это более эффективно, поскольку оно не умножает строки перед агрегацией, как это делают как попытка OP, так и outer join решение.

2. @GMB Я бы ожидал, что Postgres будет достаточно умен, чтобы оптимизировать декартово произведение, зная, что на агрегатную функцию не влияют повторяющиеся значения. Но я доверяю вашим инстинктам больше, чем моим 🙂

3. Второе решение должно быть основным. Здесь нет никакой связи между a / b / c, которые требуются здесь