我有以下给定的表结构(我删除了一些列并创建了一个存根)以支持版本控制并减少数据重复。想象一下文章评论过程,而每个步骤都存储在数据库(article_meta)中。每当文章本身发生变化时,数据也会存储在数据库中。 版本控制是通过对前一个(pre_meta_id)的引用来完成的。
WITH
t_article_meta (id, pre_meta_id, user_id, state) as (
values (1, NULL, 101, 'submitted')
union all values (2, 1, 7, 'inreview')
union all values (3, 2, 7, 'rejected')
union all values (4, 3, 101, 'submitted')
union all values (5, NULL, 202, 'submitted')
union all values (6, 5, 7, 'inreview')
union all values (7, 6, 7, 'accepted')
union all values (8, 4, 7, 'inreview')
union all values (9, 8, 7, 'accepted')
),
t_article (id, meta_id, content) as (
values (1, 1, 'Hello wordl')
union all values (2, 4, 'Hello world')
union all values (3, 5, 'Lorem ipsum doloret')
)
SELECT ...;
现在我想创建一个以某种方式组合元数据和文章数据的视图,即使没有直接引用(只有间接通过前任)。
id | pre_meta_id | user_id | state | content (left join) | content (I want to have)
---|-------------|---------|-----------|---------------------|-------------------------
1 | NULL | 101 | submitted | Hello wordl | Hello wordl
2 | 1 | 7 | inreview | NULL | Hello wordl
3 | 2 | 7 | rejected | NULL | Hello wordl
4 | 3 | 101 | submitted | Hello world | Hello world
5 | NULL | 202 | submitted | Lorem ipsum doloret | Lorem ipsum doloret
6 | 5 | 7 | inreview | NULL | Lorem ipsum doloret
7 | 6 | 7 | accepted | NULL | Lorem ipsum doloret
8 | 4 | 7 | inreview | NULL | Hello world
9 | 8 | 7 | accepted | NULL | Hello world
如何以表现的方式在DB2中实现类似的东西?我的第一个想法是:加入一个函数(让前一个文章与相关文章相关)对我来说听起来真的很贵。
答案 0 :(得分:1)
这个SQL可以完成这项工作:
SELECT m.id, successor_id, user_id, state, content,
last_value(content,'IGNORE NULLS') over (order by m.id) as last_value
FROM article_meta m
LEFT JOIN article a
ON m.id = a.article_meta_id
ORDER BY m.id
将表与aditional列组合在一起的常规联接(使用另一个名称与预期结果进行比较以显示差异) 您可能希望重命名该列并删除内容以获得与预期结果完全匹配的内容。
对于调整后的需求,SQL变得更复杂,因为我们必须定义递归查询以获取所有子项的标题/内容 - 它将如下所示:
with temp (id, pre_meta_id, user_id, state, level, parent, root) as (
select m.id, m.pre_meta_id, m.user_id, m.state, 1 as level, m.pre_meta_id as parent, m.id as root
from article_meta m, article a
where m.id = a.meta_id
union all
select m.id, m.pre_meta_id, m.user_id, m.state, level + 1 as level, t.id as parent, t.root
from temp t, article_meta m
where m.pre_meta_id = t.id
and m.id not in (select meta_id from article)
and level < 10
)
select *
from temp t
left join article a
on t.root = a.meta_id
order by 1