内部连接两个表,聚合varchar字段

时间:2011-10-25 06:49:42

标签: oracle concat

抱歉,我稍微改了一下我的问题。 我有两个表,我想合并它们

  TERMS_TABLE

 ID  | TERMS
 309 | 'hardware'
 309 | 'software'

TFIDF_TABLE

  ID | TERMS
 309 |'computer,phone,mp3....'

现在我想将TERMS_TABLE的TERMS列添加到TFIDF_TABLE的术语列中

结果应为:

NEW_TFIDF_TABLE

  ID | TERMS
 309 |'computer,phone,mp3....,hardware,software'

我试试这段代码:

Insert into    NEW_TFIDF_TABLE
SELECT T.ID, T.TERMS ||', '|| TT.TERMS FROM TFIDF_TABLE T
INNER JOIN TERMS_TABLE TT  ON  T.ID=TT.ID

但它没有做我想要的 我怎样才能做到这一点 ?

修改:我忘记了一个问题。如果TFIDF_TABLE已包含TERMS_TABLE的TERMS  那么我不应该将这个术语插入NEW_TFIDF_TABLE。要做这个控制机制我该怎么办?

示例:

TERMS_TABLE

 ID  | TERMS
 309 | 'hardware'
 309 | 'software'
 309 | 'computer'



TFIDF_TABLE

  ID | TERMS
 309 |'computer,phone,mp3....'

结果:

NEW_TFIDF_TABLE

  ID | TERMS
 309 |'computer,phone,mp3....,hardware,software'

2 个答案:

答案 0 :(得分:4)

如果您使用的是Oracle 11g,则可以使用LISTAGG功能,如下所示:

Insert into    NEW_TFIDF_TABLE
SELECT T.ID, T.TERMS ||', '|| LISTAGG(TT.TERMS, ',') 
FROM TFIDF_TABLE T
INNER JOIN TERMS_TABLE TT  ON  T.ID=TT.ID
GROUP BY t.ID, t.TERMS /* assuming the id is unique in t */

如果您使用的是早期版本,则可以使用包创建自己的聚合函数。我已经构建了这个FNC_CONCATCOMMASEPARATED函数,我经常使用它。

CREATE OR REPLACE TYPE "AT_CONCATCOMMASEPARATED" as object
(
  V_CONCAT varchar2(32767), -- concatenated strings

  static function ODCIAggregateInitialize(
    P_CONTEXT in out AT_CONCATCOMMASEPARATED)
  return number,

  member function ODCIAggregateIterate(
    self  in out AT_CONCATCOMMASEPARATED,
    P_VALUE in     varchar2)
  return number,

  member function ODCIAggregateTerminate(
    self     in  AT_CONCATCOMMASEPARATED,
    P_RESULT out varchar2,
    P_FLAGS  in  number)
  return number,

  member function ODCIAggregateMerge(
    self      in out AT_CONCATCOMMASEPARATED,
    P_CONTEXT in     AT_CONCATCOMMASEPARATED)
  return number
);

create or replace type body AT_CONCATCOMMASEPARATED is

static function ODCIAggregateInitialize(
  P_CONTEXT in out AT_CONCATCOMMASEPARATED)
return number
is
begin
  if P_CONTEXT is null then
    P_CONTEXT := AT_CONCATCOMMASEPARATED('');
  else
    P_CONTEXT.V_CONCAT := null;
  end if;

  return ODCIConst.Success;
end;

member function ODCIAggregateIterate(
  self    in out AT_CONCATCOMMASEPARATED,
  P_VALUE in     varchar2)
return number
is
begin
  if self.V_CONCAT is null then
    self.V_CONCAT := P_VALUE;
  else
    self.V_CONCAT := self.V_CONCAT || ', ' || P_VALUE;
  end if;

  return ODCIConst.Success;
end;

member function ODCIAggregateTerminate(
  self     in  AT_CONCATCOMMASEPARATED,
  P_RESULT out varchar2,
  P_FLAGS  in  number)
return number
is
begin
  P_RESULT := substr(self.V_CONCAT, 0, 4000);

  return ODCIConst.Success;
end;

member function ODCIAggregateMerge(
  self      in out AT_CONCATCOMMASEPARATED,
  P_CONTEXT in     AT_CONCATCOMMASEPARATED)
return number
is
begin
  if P_CONTEXT.V_CONCAT is not null then
    if self.V_CONCAT is null then
      self.V_CONCAT := P_CONTEXT.V_CONCAT;
    else
      self.V_CONCAT := self.V_CONCAT || ', ' || P_CONTEXT.V_CONCAT;
    end if;
  end if;

  return ODCIConst.Success;
end;

end;

create or replace function FNC_CONCATCOMMASEPARATED (input varchar2) return varchar2
aggregate using AT_CONCATCOMMASEPARATED;

然后,insert语句变为:

Insert into    NEW_TFIDF_TABLE
SELECT T.ID, T.TERMS ||', '|| FNC_CONCATCOMMASEPARATED(TT.TERMS) 
FROM TFIDF_TABLE T
INNER JOIN TERMS_TABLE TT  ON  T.ID=TT.ID
GROUP BY t.ID, t.TERMS /* assuming the id is unique in t */

答案 1 :(得分:0)

使用(适用于Oracle 9i及更高版本):

INSERT INTO NEW_TFIDF_TABLE (ID, TERMS)
SELECT DISTINCT 
TT.ID, 
T.TERMS || ',' || XMLAGG (XMLELEMENT (C, TT.TERMS) ORDER BY TT.TERMS ASC).EXTRACT ('//text()') , ',') AS TERMS
FROM TFIDF_TABLE T
INNER JOIN TERMS_TABLE TT ON T.ID=TT.ID