数据模型

在数据库中,一个人被表示为一个元表行,该行具有一个名称和多个属性,这些属性作为键值对存储在数据表中(键和值在单独的列中).

现在有一个查询来检索所有用户(name)及其所有属性(data).属性在单独的列中作为JSON对象返回.下面是一个例子:

name      data
Florian   { "age":25 }
Markus    { "age":25, "color":"blue" }
Thomas    {}

SQL命令如下所示:

SELECT
  name,
  json_object_agg(d.key, d.value) AS data,
FROM meta AS m
JOIN (
  JOIN d.fk_id, d.key, d.value AS value FROM data AS d
  ) AS d
ON d.fk_id = m.id
GROUP BY m.name;

问题

现在我面临的问题是,像Thomas这样没有任何属性存储在key-value表中的用户,没有使用我的 Select 函数显示.这是因为它只做JOIN而不做LEFT OUTER JOIN.

如果我使用LEFT OUTER JOIN,那么我遇到了一个问题,那就是json_object_aggtry 聚合NULL个值,结果以错误告终.

方法

1.返回键和值的空列表

所以我试着判断用户的key-column是否为NULL,并返回一个空数组,这样json_object_agg就会创建一个空的JSON对象.

但实际上,SQL中并没有创建空数组的函数.我找到的最接近的东西是:

select '{}'::text[];

结合COALESCE,查询如下所示:

json_object_agg(COALESCE(d.key, '{}'::text[]), COALESCE(d.value, '{}'::text[])) AS data

但如果我try 使用这个,我会得到以下错误:

ERROR:  COALESCE types text and text[] cannot be matched
LINE 10:     json_object_agg(COALESCE(d.key, '{}'::text[]), COALES...
                                                ^
Query failed
PostgreSQL said: COALESCE types text and text[] cannot be matched

所以在运行时d.key看起来是一个单一的值,而不是一个array.

2.拆分JSON创建并返回空列表

所以我试着拿json_object_agg把它换成json_object把我的 keys 换掉:

json_object(COALESCE(array_agg(d.key), '{}'::text[]), COALESCE(array_agg(d.value), '{}'::text[])) AS data

但我得到的误差是null value not allowed for object key.因此COALESCE不会判断数组是否为空.

问题

那么,是否有一个函数来判断连接列是否为空,如果为空,则只返回一个简单的JSON对象?

或者有没有其他解决方案可以解决我的问题?

推荐答案

left joincoalesce().默认值为'{}'::json.

select name, coalesce(d.data, '{}'::json) as data
from meta m
left join (
    select fk_id, json_object_agg(d.key, d.value) as data
    from data d
    group by 1
    ) d
on m.id = d.fk_id;

  name   |                data                
---------+------------------------------------
 Florian | { "age" : "25" }
 Marcus  | { "age" : "25", "color" : "blue" }
 Thomas  | {}
(3 rows)    

Postgresql相关问答推荐

如何使用Docker安装PostgreSQL扩展

哪种数据类型是除法的结果?

在PostgreSQL中是否有与SQLite R*Tree类似功能?

supabase 中的交易

为什么我的唯一索引在 Postgresql 中不起作用?

使用doobie,如何将Scala case类映射到带有类型tstzmultirange的PostgreSQL列?

需要用 jack/pgx 更新 golang 中复合类型的 PSQL 行

是否可以短时间运行 VACUUM FULL 并获得一些好处?

Psycopg2 在大型 Select 查询中耗尽内存

从 Postgres 字段中的多个值中进行 Select

psql中set、\set和\pset的区别

无法向 postgresql 数据库授予用户权限(对于 rails 应用程序)

断言错误:Django-rest-Framework

Rails 4 迁移: has_and_belongs_to_many table name

PostgreSQL:使用 psql 命令行实用程序时 Windows 上的编码问题

django.db.utils.IntegrityError:duplicate key value violates unique constraint "django_content_type_pkey"

在 Spring Boot 应用程序中禁用表重新创建

有没有办法确保 WHERE 子句在 DISTINCT 之后发生?

学习 PL/pgSQL 的好资源?

SQL:子查询的列太多