Tenho a seguinte estrutura de tabela em meu banco de dados Postgres: tabela chat_channel
possui uma coluna otherUserId
que pode ser unida com tabela a coluna userId
de outra tabela, profile
. A tabela profile
possui colunas userId
que podem ser unidas à coluna senderUserId
ou recipientUserId
na tabela note
.
Para qualquer linha que chat_channel
corresponda a determinados critérios de consulta, desejo extrair a única linha de profile
onde chat_channel."otherUserId" = profile."userId"
(como colunas extras retornadas da consulta). Também quero extrair colunas da linha correspondente note
para cada uma das duas userId
correspondências possíveis: where profile."userId" = note."senderUserId"
e where profile."userId" = note."recipientUserId"
.
Estou tendo problemas para descobrir como criar um alias adequado de colunas para essa consulta duplamente aninhada, visto que a consulta interna ingressa na mesma tabela duas vezes.
Tenho que criar um alias para as colunas, pois estou retornando colunas da mesma tabela duas vezes nas linhas de resultados. Além disso, as tabelas compartilham colunas com o mesmo nome (principalmente id
).
Tentativa (1):
SELECT "chat_channel"."id" "chat_channel.id",
"chat_channel"."channelId" "chat_channel.channelId",
"chat_channel"."userId" "chat_channel.userId",
"chat_channel"."otherUserId" "chat_channel.otherUserId",
"chat_channel"."sortByDateTime" "chat_channel.sortByDateTime",
"profile_other_user"."userId" "profile_other_user.userId",
"profile_other_user"."name" "profile_other_user.name",
"note_viewer_sent"."id" "note_viewer_sent.id", -- (a)
"note_viewer_sent"."senderUserId" "note_viewer_sent.senderUserId",
"note_viewer_sent"."recipientUserId" "note_viewer_sent.recipientUserId",
"note_viewer_sent"."noteText" "note_viewer_sent.noteText",
"note_viewer_received"."id" "note_viewer_received.id",
"note_viewer_received"."senderUserId" "note_viewer_received.senderUserId",
"note_viewer_received"."recipientUserId" "note_viewer_received.recipientUserId",
"note_viewer_received"."noteText" "note_viewer_received.noteText"
FROM "chat_channel"
LEFT JOIN LATERAL (
SELECT "profile_other_user"."id",
"profile_other_user"."userId",
"profile_other_user"."name"
FROM "profile" "profile_other_user"
LEFT JOIN LATERAL (
SELECT "note_viewer_sent"."id",
"note_viewer_sent"."senderUserId",
"note_viewer_sent"."recipientUserId",
"note_viewer_sent"."noteText"
FROM "note" "note_viewer_sent" -- (b)
WHERE "note_viewer_sent"."recipientUserId" = "profile_other_user"."userId"
AND "note_viewer_sent"."senderUserId" = $viewerUserId
LIMIT 1
) AS "note_viewer_sent" ON TRUE -- (c)
LEFT JOIN LATERAL (
SELECT "note_viewer_received"."id",
"note_viewer_received"."senderUserId",
"note_viewer_received"."recipientUserId",
"note_viewer_received"."noteText"
FROM "note" "note_viewer_received"
WHERE "note_viewer_received"."senderUserId" = "profile_other_user"."userId"
AND "note_viewer_received"."recipientUserId" = $viewerUserId
LIMIT 1
) AS "note_viewer_received" ON TRUE
WHERE "chat_channel"."otherUserId" = "profile_other_user"."userId"
LIMIT 1
) AS "profile_other_user" ON TRUE
WHERE "chat_channel"."userId" = $viewerUserId
ORDER BY "chat_channel"."sortByDateTime" DESC
Problemas com isso:
- Isso dá
ERROR: missing FROM-clause entry for table "note_viewer_sent"
na linha marcada-- (a)
. - Tentar criar um alias para a tabela (
-- (b)
) não resolve o problema. - Tentar criar um alias para os resultados da consulta mais profunda (
-- (c)
) não resolve o problema.
Tentativa (2):
No entanto, se eu fizer a FROM
cláusula de nível superior
FROM "chat_channel", "note" "note_viewer_sent", "note" "note_viewer_received"
então o erro não é mais gerado, mas as WHERE
cláusulas mais internas parecem ser ignoradas:
WHERE "note_viewer_sent"."recipientUserId" = "profile_other_user"."userId"
AND "note_viewer_sent"."senderUserId" = $viewerUserId
Especificamente, cada linha do conjunto de resultados contém colunas da mesma linha (errada) de notes
, para a qual a WHERE
condição nem sequer é válida.
Além disso, parece que o efeito padrão de colocar várias tabelas FROM
é obter um produto cruzado das tabelas. (Não posso reproduzir isso agora, mas a certa altura eu estava recebendo uma cópia de cada linha de profile
para cada linha de chat_channel
e as LIMIT 1
consultas internas estavam sendo ignoradas.)
Alguma idéia sobre o que estou fazendo de errado aqui?