自定义函数字符串聚合顺序PLSQL

时间:2015-10-29 20:30:18

标签: oracle plsql oracle10g

这是一个在oracle中聚合字符串的自定义函数。

 Date Fruit   Number
1      Apple    1
1      Apple    4
1      Apple    3
1      Kiwi     6
1      Kiwi     10

转向

Date     Fruit   Number
 1     Apple    1-3-4
 1     Kiwi     6-10

使用

 SELECT Date,fruit, string_agg(number) AS Agg
 FROM   fruit
 GROUP BY Date,fruit

string_agg是由下面的代码创建的函数

 CREATE OR REPLACE TYPE t_string_agg AS OBJECT
(
  g_string  VARCHAR2(32767),

 STATIC FUNCTION ODCIAggregateInitialize(sctx  IN OUT  t_string_agg)
 RETURN NUMBER,

MEMBER FUNCTION ODCIAggregateIterate(self   IN OUT  t_string_agg,
                                   value  IN      VARCHAR2 )
 RETURN NUMBER,

 MEMBER FUNCTION ODCIAggregateTerminate(self         IN   t_string_agg,
                                     returnValue  OUT  VARCHAR2,
                                     flags        IN   NUMBER)
RETURN NUMBER,

MEMBER FUNCTION ODCIAggregateMerge(self  IN OUT  t_string_agg,
                                 ctx2  IN      t_string_agg)
RETURN NUMBER
);
/
SHOW ERRORS


CREATE OR REPLACE TYPE BODY t_string_agg IS
STATIC FUNCTION ODCIAggregateInitialize(sctx  IN OUT  t_string_agg)
RETURN NUMBER IS
BEGIN
sctx := t_string_agg(NULL);
RETURN ODCIConst.Success;
END;

MEMBER FUNCTION ODCIAggregateIterate(self   IN OUT  t_string_agg,
                                   value  IN      VARCHAR2 )
RETURN NUMBER IS
BEGIN
SELF.g_string := self.g_string || ',' || value;
RETURN ODCIConst.Success;
END;

MEMBER FUNCTION ODCIAggregateTerminate(self         IN   t_string_agg,
                                     returnValue  OUT  VARCHAR2,
                                     flags        IN   NUMBER)
RETURN NUMBER IS
BEGIN
returnValue := RTRIM(LTRIM(SELF.g_string, ','), ',');
RETURN ODCIConst.Success;
END;

MEMBER FUNCTION ODCIAggregateMerge(self  IN OUT  t_string_agg,
                                 ctx2  IN      t_string_agg)
RETURN NUMBER IS
BEGIN
SELF.g_string := SELF.g_string || ',' || ctx2.g_string;
RETURN ODCIConst.Success;
END;
END;
/
 SHOW ERRORS


 CREATE OR REPLACE FUNCTION string_agg (p_input VARCHAR2)
 RETURN VARCHAR2
 PARALLEL_ENABLE AGGREGATE USING t_string_agg;
 /
 SHOW ERRORS

但问题是我不能按照我希望的方式按顺序排序字符串。如何修改自定义函数代码以按照数字或类似的顺序按特定顺序进行聚合?

顺便说一句:我的版本是10g,所以我不能使用listagg。可以修改此代码以便通过某个输入进行排序吗?谢谢!

1 个答案:

答案 0 :(得分:0)

不要重新发明轮子。使用 LISTAGG

CREATE TABLE tab("Date" INT, Fruit VARCHAR(100), "Number" INT);

INSERT INTO tab  VALUES (1      ,'Apple',    1);
INSERT INTO tab  VALUES (1      ,'Apple',     4);
INSERT INTO tab  VALUES (1      ,'Apple',     3);
INSERT INTO tab  VALUES (1      ,'Kiwi',      6);
INSERT INTO tab  VALUES (1      ,'Kiwi',      10);


SELECT DISTINCT "Date", Fruit,
     LISTAGG ("Number" , '-') 
     WITHIN GROUP (ORDER BY "Date") OVER(PARTITION BY "Date", Fruit)  AS "Number"
FROM tab;

SqlFiddleDemo

警告:

请注意,您需要ORDER BY列。在这种情况下,如果查询将以不同的顺序读取数据,则您不会使用升序orde的列并使用具有所有相同值的Date。你应该有类似的东西:

ID Date Fruit   Number
1  1    Apple    1
2  1    Apple    4
3  1    Apple    3
4  1    Kiwi     6
5  1    Kiwi     10

LISTAGG ("Number" , '-') 
WITHIN GROUP (ORDER BY ID ASC) OVER(PARTITION BY "Date", Fruit)  AS "Number"

修改

LISTAGG 可从 Oracle 11

获取