我有一个像这样的postgres表。
+----+-----------+----------------------+--------+
| id | Key | Value | userId |
+----+-----------+----------------------+--------+
| 1 | email | thomas@reggi.com | 1 |
| 2 | firstName | thomas | 1 |
| 3 | lastName | reggi | 1 |
| 4 | email | new.thomas@reggi.com | 1 |
+----+-----------+----------------------+--------+
我正在寻找一种方法来减少"这个表下到一个json对象。
{
"email": "new.thomas@reggi.com",
"firstName": "thomas",
"lastName": "reggi"
}
只使用postgres,我能接近多少?
答案 0 :(得分:2)
如果该表名为data
,请尝试此操作(jsonb_pretty
仅用于显示目的):
SELECT jsonb_pretty(
jsonb_object_agg(key, value ORDER BY id)
)
FROM data
WHERE userid = 1;
┌──────────────────────────────────────┐
│ jsonb_pretty │
├──────────────────────────────────────┤
│ { ↵│
│ "email": "new.thomas@reggi.com",↵│
│ "lastName": "reggi", ↵│
│ "firstName": "thomas" ↵│
│ } │
└──────────────────────────────────────┘
(1 row)
这取决于jsonb
不保留重复键的功能。
它还依赖于jsonb
将始终保留最后添加的键/值对的事实。
答案 1 :(得分:1)
如果您想始终拥有密钥的最新值,可以使用CTE
和RANK()
窗口函数:
SELECT * FROM p;
┌────┬───────────┬──────────────────────┬────────┬────────────────────────────┐
│ id │ key │ value │ userid │ modification_time │
├────┼───────────┼──────────────────────┼────────┼────────────────────────────┤
│ 1 │ email │ thomas@reggi.com │ 1 │ 2016-10-05 12:53:32.936704 │
│ 2 │ firstName │ thomas │ 1 │ 2016-10-05 12:53:32.936704 │
│ 3 │ lastName │ reggi │ 1 │ 2016-10-05 12:53:32.936704 │
│ 4 │ email │ new.thomas@reggi.com │ 1 │ 2016-11-06 15:53:48.025775 │
└────┴───────────┴──────────────────────┴────────┴────────────────────────────┘
(4 rows)
WITH info_with_rank_for_user AS (
SELECT userId,
modification_time,
value,
key,
RANK() OVER (PARTITION BY userId, key ORDER BY id DESC)
FROM p
)
SELECT userId,
json_object_agg(key, value),
MAX(modification_time) AS last_settings_modification_time
FROM info_with_rank_for_user
WHERE rank = 1
GROUP BY userId
;
┌────────┬────────────────────────────────────────────────────────────────────────────────────┬─────────────────────────────────┐
│ userid │ json_object_agg │ last_settings_modification_time │
├────────┼────────────────────────────────────────────────────────────────────────────────────┼─────────────────────────────────┤
│ 1 │ { "email" : "new.thomas@reggi.com", "firstName" : "thomas", "lastName" : "reggi" } │ 2016-11-06 15:53:48.025775 │
└────────┴────────────────────────────────────────────────────────────────────────────────────┴─────────────────────────────────┘
(1 row)