4

在这里使用 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 次,每个文件只包含一个不同的文本行,然后根据项目将它们全部重新匹配并以这种方式连接......但是哇,那是多么混乱:)

请帮忙 :)

4

5 回答 5

6

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评论中的常规递归查询。

于 2013-08-31T00:25:08.957 回答
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 编写并在其上运行的)

于 2013-09-03T19:50:09.887 回答
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 
于 2014-10-30T16:13:57.160 回答
0

DB2 for i没有可用于此目的的聚合函数,也不支持用户定义的聚合函数。

唯一的选择是存储过程或“客户端”聚合。

于 2013-08-30T18:24:22.243 回答
0

@WarrenT——在 i 上工作了 16 年多之后,我以为我是那些猫中的一员……但你令人不安地证明了我错了。:) 对 SQL 的反应很好。是的,我看到了一些立即使用它的机会!!!

不幸的是,我仅限于 V5R4 ......它将作为存储过程调用工作,例如 .NET Web 应用程序?

于 2013-09-05T13:15:42.447 回答