横向连接查询返回带括号的值。如何去除它?

her*_*anl 3 sql postgresql lateral-join

我正在使用 Postgres 作为聊天应用程序。我有两张表,一张包含对话 ID 和参与者,另一张表包含消息。

我正在运行以下查询来获取用户的所有对话,并使用横向联接在结果中包含最后一条消息:

select c.id, c.title, c.members, max(m.created_at) delivered_at, last_message
from conversations c
join messages m on c.id = m.conversation_id
left join lateral (select message from messages m where c.id = m.conversation_id order by created_at desc limit 1) last_message on true 
where array[4] <@ c.members 
group by c.id, last_message
order by delivered_at desc
Run Code Online (Sandbox Code Playgroud)

这有效,但消息返回为(message)而不是message

我真的不知道为什么。有什么我可以做的,这样我就不必替换括号作为额外的步骤?

Kaz*_*Nur 5

您需要在选择列表中提及列名称,而不是表名称或别名:

select c.id, c.title, c.members, max(m.created_at) delivered_at, last_message
from conversations c
join messages m on c.id = m.conversation_id
left join lateral (select message from messages m where c.id = m.conversation_id order by created_at desc limit 1) as t(last_message) on true 
where array[4] <@ c.members 
group by c.id, last_message
order by delivered_at desc
Run Code Online (Sandbox Code Playgroud)

解释:

在 PostgreSQL 中,查询中对表名(或别名)的引用实际上是对表当前行的复合值的引用。例如,如果我们有一个如上所示的表 inventory_item,我们可以编写:

SELECT c FROM inventory_item c;
Run Code Online (Sandbox Code Playgroud)

此查询生成单个复合值列,因此我们可能会得到如下输出:

      c
------------------------
 ("fuzzy dice",42,1.99)

(1 row)
Run Code Online (Sandbox Code Playgroud)

但请注意,简单名称与表名称之前的列名称相匹配,因此此示例仅在查询表中没有名为 c 的列时才有效。

普通的限定列名语法 table_name.column_name 可以理解为将字段选择应用于表当前行的复合值。(出于效率原因,实际上并未以这种方式实现。)

当我们写的时候

SELECT c.* FROM inventory_item c;
Run Code Online (Sandbox Code Playgroud)

然后,根据 SQL 标准,我们应该将表的内容扩展为单独的列:

姓名 供应商ID 价格
模糊骰子 42 1.99
(1 row)
Run Code Online (Sandbox Code Playgroud)

就好像查询是

SELECT c.name, c.supplier_id, c.price FROM inventory_item c;
Run Code Online (Sandbox Code Playgroud)

引用自以下链接: https://www.postgresql.org/docs/current/rowtypes.html#ROWTYPES-USAGE