假设有以下情况:

create schema bv;
create table bv.user(id bigint primary key);
create table bv.user_photo (
  id bigint primary key,
  url varchar(255) not null,
  user_id bigint references bv.user(id)
);

insert into bv.user values (100), (101);
insert into bv.user_photo values
  (1, 'https://1.com', 100),
  (3, 'https://3.com', 100),
  (4, 'https://4.com', 101),
  (2, 'https://2.com', 100);

我想 for each 用户查询并构建一个对象,并在结果中只包含最新的图像.

这就是我所拥有的:

select
  json_build_object(
    'id', u.id,
    'latest_image', up.url
  ) user
from bv.user u
left join bv.user_photo up
  on u.id = up.user_id

然而,这将返回:

[
  {"id" : 100, "url" : "https://2.com"},
  {"id" : 100, "url" : "https://3.com"},
  {"id" : 100, "url" : "https://1.com"},
  {"id" : 101, "url" : "https://4.com"}
]

然而,预期的结果是:

[
  {"id" : 100, "url" : "https://3.com"},
  {"id" : 101, "url" : "https://4.com"}
]

我试过用distinct:

select distinct on(u.id)
  json_build_object(
    'id', u.id,
    'url', up.url
  ) user
from bv.user u
left join bv.user_photo up
  on u.id = up.user_id
order by u.id, up.id DESC

但我的问题是,这是不是正确的方法?我觉得在这种情况下我不应该用distinct.

推荐答案

这是正确的方法,在这样的情况下,你一定要用distinct on.普通的distinct-不,distinct on-是:

SELECT DISTINCT ON ( expression [, ...] )只保留给定表达式求值为相等的每组行中的第一行.

这里我遗漏的一件事是,您期望的是这些对象的单个数组,但您的查询在单独的行中返回每个对象.你需要json_agg()分才能收集到它们:demo

select json_agg("user" order by id) as "user_array"
from(select distinct on(u.id) u.id,
      json_build_object('id', u.id,
                        'url', up.url) as "user"
     from bv.user u 
     left join bv.user_photo up
            on u.id = up.user_id
     order by u.id, up.id DESC) subquery;
user_array
[ {"id" : 100, "url" : "https://3.com"}, {"id" : 101, "url" : "https://4.com"} ]

Sql相关问答推荐

Oracle SQL对列进行汇总并在列表底部显示总计

表名数组

获取每个帖子的匹配关键字列表

使用交叉应用透视表在SQL中转换分段时间段&

SQL查询视图与连接?

Postgres trunc_date删除一个月

有没有办法在每次计算每一行的数据时更新2个值?

将主表与历史表连接以获取主表的当前汇率以及历史表中的上一个和最后一个汇率

将重复的值更新为下一个空闲数字

查找表中特定值的上次更新日期

如何设计一个调用嵌套函数并仅在所有被调用的嵌套函数都提交时才提交的事务,例如,如果一个子函数失败则中止?

SQL按日期分组字段和如果日期匹配则求和

无法将发票与产品价格相关联

每小时 Select 1行

PostgreSQL-按距离阈值挤压相邻行的性能

如何在连接中使用三个不同的列,从而在PostgreSQL中只获得两个列?

使用同一个表,为什么IN、NOT IN、NOT EXISTS和EXISTS有不同的输出?

将 MERGE 语句与 Oracle PL/SQL 表类型一起使用时,导致无效数据类型错误的原因是什么?

如果 SQL 中不存在数据,如何根据某个 ID 为所有日期添加前一行

如何在 Oracle 中获取此变量的值?