Vamos considerar que tenho as seguintes tabelas:
CREATE TABLE users(
id serial PRIMARY KEY,
age integer
)
CREATE TABLE products(
id serial PRIMARY KEY,
sku character varying(255),
user_id integer REFERENCES users
)
Então, basicamente, um produto pertenceria a um usuário e um usuário poderia ter muitos produtos.
Eu quero a capacidade de carregar usuários com seus produtos fazendo a agregação no nível do banco de dados (talvez erroneamente, mas suponho que seria mais fácil e provavelmente mais eficiente do que executar algum código de agregação na minha camada de aplicativo: Postgres vem com boas funções de agregação, por que não usando-os !)
Então eu executaria algo como
SELECT "users".*, json_agg("products".*) as "products"
FROM "users" LEFT JOIN "products" ON "users"."id" = "products"."user_id"
GROUP BY "users"."id"
Tudo bem, meu driver pode analisar estruturas JSON e não tenho nada para fazer no lado da camada do aplicativo.
O problema surge se eu quiser introduzir algum tipo de paginação:
WITH "users" AS (SELECT * FROM "users" ORDER BY "id" LIMIT 20)
SELECT "users".*, json_agg("products".*) as "products"
FROM "users" LEFT JOIN "products" ON "users"."id" = "products"."user_id"
GROUP BY "users"."id"
Eu tenho o erro conhecido
ERRO: a coluna "users.age" deve aparecer na cláusula GROUP BY ou ser usada em uma função agregada
Como o "users"."id" não é considerado a chave primária da tabela temporária criada pela minha subconsulta
Eu poderia corrigi-lo adicionando todas as colunas de usuários na cláusula group by. Mas acho isso problemático e uma pena, pois tenho certeza de que "users".."id" definirá de maneira única um item da minha subconsulta.
Então, eu gostaria de saber se existe uma maneira de dizer ao mecanismo de banco de dados "usuários".."id" é algum tipo de chave primária para minha subconsulta?
Se não, você vê uma maneira melhor?
EDIT: Esta pergunta é bastante semelhante (3 anos de idade)
Obrigado
IMHO sua primeira consulta deve lançar a mesma mensagem de erro.
Mas você pode mover
json_agg
para uma subconsulta em vez de juntar as duas tabelas, então você pode facilmente limitar o número de linhas retornadas.db<>fique aqui