sql - 有没有办法从聚合 sql 查询中获取嵌套表?
问题描述
我有两张桌子:
- 具有 id 和一些数据字段的帖子
- 标签有一个 post id(pots.id 上的forein 键)、一个键和一个值字段(没有 id 或索引,只有元组)
帖子
| id | title | body |
+----+-------+------+
| 1 | t1 | b1 |
+----+-------+------+
| 2 | t2 | b2 |
+----+-------+------+
标签
| post | key | value |
+------+-----+-------+
| 1 | bar | baz |
+------+-----+-------+
| 1 | foo | bar |
+------+-----+-------+
如果我想检索一些带有自己标签的帖子,可以使用类似的查询
select posts.*, tags.*
from posts
left join tags
on posts.id = tags.post
我会得到
| id | title | body | post | key | value |
+----+-------+------+------+-----+-------+
| 1 | t1 | b1 | 1 | bar | baz |
+----+-------+------+------+-----+-------+
| 1 | t1 | b1 | 1 | foo | bar |
+----+-------+------+------+-----+-------+
| 2 | t2 | b2 | | | |
+----+-------+------+------+-----+-------+
但是我想为 post 获得单行,所以我用这个查询以 json 方式按 Id 和 group_concat 对标签的数据进行分组(请注意,我正在 SQLite db 上进行这个实验,|| 是字符串连接运算符)
select posts.*, "{" || group_concat('"' || tags.key || '": "' || tags.value || '"') || "}" as tags
from posts
left join tags
on posts.id = tags.post
group by posts.id
这就是结果
| id | title | body | tags |
+----+-------+------+-----------------------------+
| 1 | t1 | b1 | {"bar": "baz","foo": "bar"} |
+----+-------+------+-----------------------------+
| 2 | t2 | b2 | |
+----+-------+------+-----------------------------+
我的问题是:有没有办法以更好的方式聚合标签结果?我的意思是更类似于普通 sql 表的东西,也许是不需要解析的东西(甚至是可查询的东西)。
我想在标签单元格中得到一个表格,像这样
| id | title | body | tags |
| | | | key | value |
+----+-------+------+-----+-------+
| 1 | t1 | b1 | bar | baz |
| | | +-----+-------+
| | | | foo | bar |
+----+-------+------+-----+-------+
| 2 | t2 | b2 | | |
+----+-------+------+-----+-------+
这是否可以通过某种方式实现(即使使用不同的 sql dbms)?
解决方案
SQL 查询的结果是由行和列组成的数据集,没有表中表或单元格中的单元格的概念。
最接近您的要求的是在null
每组的第一行之后返回 s 或空白的查询:
SELECT CASE WHEN rn = 1 THEN t.id END id,
CASE WHEN rn = 1 THEN t.title END title,
CASE WHEN rn = 1 THEN t.body END body,
t.post, t.key, t.value
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY p.id ORDER BY t.key) rn
FROM posts p LEFT JOIN tags t
ON t.post = p.id
) t
ORDER BY t.id, t.rn
结果:
ID | 标题 | 身体 | 邮政 | 钥匙 | 价值 |
---|---|---|---|---|---|
1 | t1 | b1 | 1 | 酒吧 | 巴兹 |
无效的 | 无效的 | 无效的 | 1 | 富 | 酒吧 |
2 | t2 | b2 | 无效的 | 无效的 | 无效的 |
或者:
SELECT CASE WHEN rn = 1 THEN t.id ELSE '' END id,
CASE WHEN rn = 1 THEN t.title ELSE '' END title,
CASE WHEN rn = 1 THEN t.body ELSE '' END body,
COALESCE(t.post, '') post,
COALESCE(t.key,'') key,
COALESCE(t.value, '') value
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY p.id ORDER BY t.key) rn
FROM posts p LEFT JOIN tags t
ON t.post = p.id
) t
ORDER BY t.id, t.rn
结果:
ID | 标题 | 身体 | 邮政 | 钥匙 | 价值 |
---|---|---|---|---|---|
1 | t1 | b1 | 1 | 酒吧 | 巴兹 |
1 | 富 | 酒吧 | |||
2 | t2 | b2 |
请参阅演示。
推荐阅读
- reactjs - 单击 ReactJS 中的链接时在新窗口中打开页面
- python - 了解 Keras 层的形状
- javascript - Angular 8:同步/顺序运行组件类方法
- google-bigquery - BigQuery 无法在 SELECT * REPLACE 中使用分析函数
- r - 无序列表中的多种文本格式
- knime - 如何保存 KNIME 循环的中间结果?
- java - 为什么在堆中创建字符串对象和字符串文字的串联?
- javascript - 浏览器刷新div对齐更改后的jquery
- javascript - 在画布中绘制 5 个点的椭圆
- wordpress - 如何在woocommerce中限制每个用户每天一个订单