DB2 for i 可以做到这一点。
也许最简洁的方法是使用其他 DB2 平台所没有的一个经常被忽视的特性——一种称为分层查询的递归查询。像许多事情一样,一旦你理解了它就相当简单,但它值得一点解释来理解它是如何工作的。
递归或分层查询可帮助您将一行连接到另一行或多行。在这种情况下,我们正在建立一个一对一的连接链。
聚合SYS_CONNECT_BY_PATH 函数将沿着从开始(或“根”)行到结束(或“叶”)行的路径连接字符串。
让我们首先将您的示例数据放入一个表中。
declare global temporary table snippets
( item varchar(10)
, seq smallint
, words varchar(30)
);
insert into snippets
values
('12755', 1, 'this item')
,('12755', 2, 'is no longer')
,('12755', 3, 'for sale')
,('abc123', 1, 'please use')
,('abc123', 2, 'another code')
,('xyz987', 1, 'obsolete')
;
让我们看看我们将用作第一阶段构建块的分层查询。
SELECT item
, seq
, CONNECT_BY_ISLEAF as flag
, SYS_CONNECT_BY_PATH(words, ' ') as phrase
FROM snippets
START WITH seq = 1
CONNECT BY PRIOR item = item and PRIOR (seq + 1) = seq
CONNECT BY子句定义从表中的一行到另一行的连接条件。
START WITH子句指定从哪一行开始连接,即“根”行。因此,我们将从 seq=1 的行开始,并连接到下一个 seq 值 (seq+1)。该行将连接到以下 seq 值,依此类推。
CONNECT_BY_ISLEAF将指示我们何时位于链中的最后一行。你马上就会明白为什么我在这里使用它。
结果如下:
ITEM SEQ FLAG PHRASE
12755 1 0 this item
12755 2 0 this item is no longer
12755 3 1 this item is no longer for sale
abc123 1 0 please use
abc123 2 1 please use another code
xyz987 1 1 obsolete
现在我们需要做的就是把它放在一个公共的表表达式中,我们可以从中只取我们想要的行。链末端的“叶子”行有完整的字符串,所以这些是要挑选的。
with q as
(
SELECT item
, seq
, CONNECT_BY_ISLEAF as flag
, SYS_CONNECT_BY_PATH(words, ' ') as phrase
FROM snippets
START WITH seq = 1
CONNECT BY PRIOR item = item and PRIOR (seq + 1) = seq
)
SELECT item
, phrase
FROM q
WHERE flag = 1
ORDER BY item
;
这给了我们:
ITEM PHRASE
abc123 please use another code
xyz987 obsolete
12755 this item is no longer for sale
你有它。
其他 DB2 平台上的人们将不得不寻找另一种解决方案,例如上面funkworm评论中的常规递归查询。