使用DB2讨论iSeries上的文件中的数据。
文件结构如下:
Item Textline Text
12755 1 this item
12755 2 is no longer
12755 3 for sale
abc123 1 please use
abc123 2 another code
xyz987 1 obsolete
我试图获得的结果是
Item Text
12755 this item is no longer for sale
abc123 please use another code
xyz987 obsolete
因此,它按项目代码分组,文本行被添加,无论有多少。
我首先在查询中尝试将文件连接到自身5次(可能有多达5个文本行),但我永远无法让它工作。
我在SQL中尝试过但是我无法获得与家庭文本正常工作的命令,并且我正在努力将标准添加到一起而不重复文本行。
有任何想法吗?
我最后的办法是将这个文件提取5次,每个文件只包含一个不同的文本行,然后根据项目将它们全部重新匹配并连接到那个方式......但是它是多么混乱:)< / p>
请帮助:)
答案 0 :(得分:6)
DB2 for i可以做到这一点。
也许最简洁的方法是使用一个经常被忽视的功能,其他DB2平台没有 - 一种称为hierarchical query的递归查询。像许多事情一样,一旦理解它就会相当简单,但理解其工作方式需要一些解释。
递归或分层查询可帮助您将一行连接到一个或多个其他行。在这种情况下,我们正在建立一对一的连接链。
聚合SYS_CONNECT_BY_PATH function将沿着从起始(或“根”)行到结束(或“叶子”)行的路径连接字符串。
让我们首先将您的样本数据放入表格中。
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子句指定从“root”行开始加入的行。所以我们将从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
现在我们需要做的就是把它放在common table expression中, 从中我们只能获取我们想要的行。链末尾的“叶子”行有完成的字符串,所以那些是要选择的。
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评论中的常规递归查询。
答案 1 :(得分:2)
如果你想创建一个可以做这种事情的用户定义函数,我写这篇文章是为了完成一项基本相同的任务:
create function GetTextBlock(inItemNo decimal(13,0))
returns varchar(1200)
begin atomic
declare outstr varchar(1200) default '';
for list_comments as
select tltx60
from msytxl
where tlcono = 1
and tldivi = ''
and tltxid = inItemNo
order by tllino
do
set outstr = outstr || trim(tltx60) || ' ';
end for;
set outstr = rtrim(outstr);
return outstr;
end
go
然后你可以在SELECT语句中使用它,如下所示:
Select ItemNo, GetTextBlock(ItemNo)
from ItemMaster
(此代码是为DB2 for i V6R1编写并使用的)
答案 2 :(得分:1)
V5R4
declare global temporary table qtemp.snippets
( item varchar(10)
, seq smallint
, words varchar(30)
);
insert into qtemp.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')
;
with q(item, seq, words, phrase) as
(
SELECT s.item
, s.seq
, s.words
, s.words phrase
FROM qtemp.snippets s
where s.seq = 1
union all
SELECT s1.item
, s1.seq
, s1.words
, q.Phrase || ' ' || s1.words phrase
FROM qtemp.snippets s1
join q on s1.item = q.item
and s1.seq = q.seq +1
)
select q.item, q.phrase from q
join (
Select q.item, max(q.seq) maxseq from q
group by item
) q1 on q.item = q1.item and q.seq = q1.maxseq
答案 3 :(得分:0)
DB2 for i没有可用于此目的的aggregate function,也不支持用户定义的聚合函数。
唯一的选择是存储过程或“客户端”聚合。
答案 4 :(得分:0)
不幸的是,我仅限于V5R4 ...它是否可以作为一个存储过程调用,比如一个.NET Web应用程序?