SQL连接同一文件中不同记录的文本字段

时间:2013-08-30 15:08:06

标签: sql ibm-midrange

使用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>

请帮助:)

5 个答案:

答案 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)

@WarrenT--在我16年多的时间之后,我以为我就是其中一只猫......但是你却令人不安地证明我错了。 :)对SQL有很好的回应。是的,我看到一些机会立即使用它!

不幸的是,我仅限于V5R4 ...它是否可以作为一个存储过程调用,比如一个.NET Web应用程序?